作者tkdmaf (皮皮快跑)
看板PHP
标题Re: [请益] mysql_fetch_array 取出的阵列数
时间Sat Jul 30 11:45:24 2011
: 如果手上有一个案子,其中某个部份是有关资料的显示处理,
: 资料是可能会由一个结构简单的 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)
1F:→ gpmm:重复说一次,我的文章并不是写给您看的,所以这些程式码 07/30 18:18
2F:→ gpmm:也不是跟你在扯这些用的,别自己拉椅子就坐下来 07/30 18:19