Re: [請益] mysql_fetch_array 取出的陣列數
: 如果手上有一個案子,其中某個部份是有關資料的顯示處理,
: 資料是可能會由一個結構簡單的 DB Table 中取得,
: ※ id / name
: 但是最後要輸出的可能形式包括:
: 下拉式選單(select)、列表、單選按鈕(radio)三種
: 在一般性的思考上,我們很可能會建立三個 function:
: function output_select ($data)
: function output_list ($data)
: function output_radio ($data)
: 三個 function 各自代表了某種輸出的實做,
: 而允許輸入的參數是 mysql_fetch_* 所取出的資料集合,
: 但如果今天突然增加一個限制條件,
: name 當中 sexy 為字首的部份顯示時必須要濾掉,
: 並且再增加一個控制條件,
: 表示當 id 小於 100 的是系統管理者,要在 name 前面加上 admin
: 那在這個思考點上的延伸很可能是增加第四、五個 function:
: function data_remove_sexy ($data)
: function data_check_add_admin ($data)
: 而我們使用上會是:
: $data = mysql_fetch_* ($sql);
: $data = data_remove_sexy ($data);
: $data = data_check_add_admin ($data);
: output_select ($data);
: 注意到哪邊很有趣了嗎?
: yap,這五個 function 實際上在處理的都是同一筆資料 $data,
: 我們可以思考如何嘗試用更結構化的方式來達成這件事。
: 類別設計的本身具有一個最強大的特性讓它成為可以承擔物件導向的一切核心,
: 那就是「物件內部自我資料處理的能力」,
: 如果僅僅將類別當作一種儲存方式來使用那是極為浪費的行為(並不是說不行),
: 因為這會將物件貶低到跟 array 或 hash table 一樣的價值層次裡,
: 也就是儲存複數資料的能力。
: 如果真的 class 在宣告後只是從外部餵給它變數,
: 那 class 和 hash table 也就只有語法撰寫上的差異而已了。
: 回到類別,如果我們試著把上面這個例子類別化,可以粗略得到以下的程式:
: class dataHandler {
: var $_data = Array ();
: function __construct ($data) {
: $this->_data = $data;
: $this->data_remove_sexy ();
: $this->data_check_add_admin ();
: }
: function data_remove_sexy () {}
: function data_check_add_admin () {}
: function output_select () {}
: function output_list () {}
: function output_radio () {}
: }
: 仔細看過我們可以發現,幾乎所有的函式(方法)都不需要額外的參數,
: 因為它們都已經成為這個類別(物件)的一部分,可以直接使用物件內部的資料。
: 這個類別在使用上大致可以像以下:
: $data = mysql_fetch_* ($sql);
: $dh = new dataHandler ($data);
: $dh->output_select ();
: 當然你可能會說,我也可以在每個 output_* 裡加上那兩個函式來節省重複的部份,
: 這樣使用起來和類別也就差不多了啊?
: 但是仔細想想,當我們需要擴充更多的前提條件或更多的輸出方法時,
: function 和 class 哪個處理起來會更容易(包括容易實做與理解)?
: 除此之外,當你朋友遇到一個相同的需求時,
: 你可以直接把這個 class 交給他,然後告訴他:
: 「只需要 new 出物件,並且把 $data 餵進去,中間的它都會幫你處理好。」
: 這就是物件導向三大特性中 - 封裝的一部分含意。
: 有沒有一種很熟悉的感覺?
: 其實當我們在使用別人已經做好的擴充類別時,也都會享受到封裝特性的優點,
: 也就是類別實際上達成了黑箱化的作業,隱匿去了使用者不需知道的細節,
: 而我們只要專注在類別本身的操作和使用上即可。
嗯!終於看到程式碼了。這樣要談內容也比較好講。
那麼如果我是你,我就會開始考慮擴充性的問題。
也因此會變成這樣的動作:
class dataHandler {
var $_data = Array ();
function __construct ($data,$filter_class = 'default') {
$this->_data = $this->_data_filter($data,$filter_class);
}
function _data_filter($data,$filter_class){
require_once($filter_class.'.php');
$filter = new $filter_class;
return $filter->filter_run($data);
}
function output_select () {}
function output_list () {}
function output_radio () {}
}
class default{
var $_data;
function filter_run($data){
$this->_data = $data;
$this->_filter_drive();
return $this->_data;
}
protected function _filter_drive(){
$this->data_remove_sexy();
$this->data_check_add_admin();
}
function data_remove_sexy () {}
function data_check_add_admin () {}
}
class my_filter extends default{
function _filter_drive(){
parent::_filter_drive();
$this->_auth_person_id();
}
function _auth_person_id();
}
這麼樣的做法,我就可以對我的過濾條件開放給其他人實作。
而不僅限定於dataHandler本身所提供的過濾法則。
假如說使用者必須使用我的default然後再加上其他的過濾原則。
他只需要對default做繼承即可。
若是只想寫自己的過濾條件。
就只要寫自己的_filter_drive()而不需要載入父類別的方法。
對於dataHandler的修改進行封閉。
但對於$filter物件卻可以無限的擴充。
甚至基於這樣的擴充法則,連output也可以進行功能性的開放。
so......如果沒有做到對擴充開放,對修改封閉的話......
那當然到最後就會發生預期之外的情形無法擴充修改的窘境了。
可惜我實在不習慣用bbs來畫UML圖......
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.118.19
※ 編輯: tkdmaf 來自: 220.132.118.19 (07/30 11:47)
→
07/30 18:18, , 1F
07/30 18:18, 1F
→
07/30 18:19, , 2F
07/30 18:19, 2F
討論串 (同標題文章)
完整討論串 (本文為第 7 之 9 篇):