浅析PHP中Collection 类的设计


Posted in PHP onJune 21, 2013

用.net开发已经很多年了,最近接触到php,发现php也很好玩。不过发现它里面没有集合Collection类,只有数组,并且数组很强。这里我用数组来包装成一个集合Collection,代码如下:

class Collection{ 
    private $_members=array();     public  function addItem($obj,$key=null) 
    { 
        if($key) 
        { 
            if(isset($this->_members[$key])) 
            { 
                throw  new exception("Key \"$key\" already in use!"); 
            } 
            else
            { 
                $this->_members[$key]=$obj; 
            } 
        } 
        else
        { 
            $this->_members[]=$obj; 
        } 
    } 
    public function removeItem($key) 
    { 
        if(isset($this->_members[$key])) 
        { 
            unset($this->_members[$key]); 
        } 
        else
        { 
            throw new exception("Invalid Key \"$key\"!"); 
        } 
    } 
    public function getItem($key) 
    { 
        if(isset($this->_members[$key])) 
        { 
            return $this->_members[$key]; 
        } 
        else
        { 
            throw new  exception("Invalid Key \"$key\"!"); 
        } 
    } 
    public function Keys() 
    { 
        return array_keys($this->_members); 
    } 
    public function legth() 
    { 
        return sizeof($this->_members); 
    } 
    public function exists($key) 
    { 
        return (isset($this->_members[$key])); 
    } 
}

现在我们来测试一下这个集合是否好用。
我们首先建立一个集合元素类Course:
class  Course 
{ 
    private $_id; 
    private $_courseCode; 
    private $_name;   public function __construct($id,$courseCode,$name) 
    { 
        $this->_id=$id; 
        $this->_courseCode=$courseCode; 
        $this->_name=$name; 
    } 
    public function getName() 
    { 
        return $this->_name; 
    } 
    public function getID() 
    { 
        return $this->_id; 
    } 
    public function getCourseCode() 
    { 
        return $this->_courseCode; 
    } 
    public function __toString() 
    { 
        return $this->_name; 
    } 
}

测试代码如下:
$courses=new Collection();
$courses->addItem(new Course(1, "001", "语文"),1);
$courses->addItem(new Course(2, "002", "数学"),2);
$obj=$courses->getItem(1);
print $obj;
我想这个集合类应该可以满足我们平日开发的需求了吧。
可是我们现在。net里面有个对象延迟加载,举个例子来说吧,假如现在有Student这个对象,它应该有很多Course,但是我们希望在访问Course之前Course是不会加载的。也就是说在实例化Student的时候Course个数为0,当我们需要Course的时候它才真正从数据库读取相应数据。就是需要我们把Collection做成惰性实例化。
修改后的Collection代码如下:
class Collection {
  private $_members = array();    //collection members
  private $_onload;               //holder for callback function
  private $_isLoaded = false;     //flag that indicates whether the callback
                                  //has been invoked
  public function addItem($obj, $key = null) {
    $this->_checkCallback();      //_checkCallback is defined a little later    if($key) {
      if(isset($this->_members[$key])) {
        throw new KeyInUseException("Key \"$key\" already in use!");
      } else {
        $this->_members[$key] = $obj;
      }
    } else {
      $this->_members[] = $obj;
    }
  }
  public function removeItem($key) {
    $this->_checkCallback();
    if(isset($this->_members[$key])) {
      unset($this->_members[$key]);
    } else {
      throw new KeyInvalidException("Invalid key \"$key\"!");
    }  
  }
  public function getItem($key) {
    $this->_checkCallback();
    if(isset($this->_members[$key])) {
      return $this->_members[$key];
    } else {
      throw new KeyInvalidException("Invalid key \"$key\"!");
    }
  }
  public function keys() {
    $this->_checkCallback();
    return array_keys($this->_members);
  }
  public function length() {
    $this->_checkCallback();
    return sizeof($this->_members);
  }
  public function exists($key) {
    $this->_checkCallback();
    return (isset($this->_members[$key]));
  }
  /**
   * Use this method to define a function to be 
   * invoked prior to accessing the collection.  
   * The function should take a collection as a 
   * its sole parameter.
   */
  public function setLoadCallback($functionName, $objOrClass = null) {
    if($objOrClass) {
      $callback = array($objOrClass, $functionName);
    } else {
      $callback = $functionName;
    }
    //make sure the function/method is valid
    if(!is_callable($callback, false, $callableName)) {
      throw new Exception("$callableName is not callable " . 
                          "as a parameter to onload");
      return false;
    }
    $this->_onload = $callback;
  }
  /**
   * Check to see if a callback has been defined and if so,
   * whether or not it has already been called.  If not,
   * invoke the callback function.
   */
  private function _checkCallback() {
    if(isset($this->_onload) && !$this->_isLoaded) {
      $this->_isLoaded = true;
      call_user_func($this->_onload, $this);
    }
  }
}

所需的Student如下:
class CourseCollection extends Collection { 
 public function addItem(Course $obj,$key=null) { 
        parent::addItem($obj,$key); 
    } 
} 
class Student{ 
    private $_id; 
    private $_name; 
    public $course;     public  function __construct($id,$name) 
    { 
        $this->_id=$id; 
        $this->_name=$name; 
        $this->course=new CourseCollection(); 
        $this->course->setLoadCallback('loadCourses',$this); 
    } 
    public function getName() 
    { 
        return $this->_name; 
    } 
    public function getID() 
    { 
        return $this->_id; 
    } 
    public function __toString() 
    { 
        return $this->_name; 
    } 
    public function loadCourses(Collection $col) 
    { 
        $col->addItem(new Course(1, "001", "语文"),1); 
        $col->addItem(new Course(2, "002", "数学"),2); 
    } 
}

调用代码如下:
$student=new Student(1, "majiang");
print $student->getName();
print $student->course->getItem(1);
PHP 相关文章推荐
解决控件遮挡问题:关于有窗口元素和无窗口元素
Jan 28 PHP
PHP备份/还原MySQL数据库的代码
Jan 06 PHP
phpMyAdmin 链接表的附加功能尚未激活问题的解决方法(已测)
Mar 27 PHP
php存储过程调用实例代码
Feb 03 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
Apr 30 PHP
php将文本文件转换csv输出的方法
Dec 31 PHP
浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
Oct 26 PHP
Laravel学习教程之路由模块
Aug 18 PHP
PHP实现生成推广海报的方法详解
Mar 14 PHP
Yii框架引入coreseek分页功能示例
Feb 08 PHP
解决Laravel无法使用COOKIE和SESSION的问题
Oct 16 PHP
PHP call_user_func和call_user_func_array函数的简单理解与应用分析
Nov 25 PHP
解析PHP无限级分类方法及代码
Jun 21 #PHP
PHP 循环删除无限分类子节点的实现代码
Jun 21 #PHP
解析左右值无限分类的实现算法
Jun 20 #PHP
解析thinkphp的左右值无限分类
Jun 20 #PHP
PHP 清空varnish 缓存的详解(包括指定站点下的)
Jun 20 #PHP
PHP array_multisort() 函数的深入解析
Jun 20 #PHP
PHP操作MongoDB GridFS 存储文件的详解
Jun 20 #PHP
You might like
php多次include后导致全局变量global失效的解决方法
2015/02/28 PHP
thinkphp微信开发(消息加密解密)
2015/12/02 PHP
PHP hebrev()函数用法讲解
2019/02/21 PHP
js获取单选按钮的数据
2006/11/27 Javascript
用JavaScript显示随机图像或引用
2009/04/21 Javascript
JS实现随机数生成算法示例代码
2013/08/08 Javascript
jQuery检测鼠标左键和右键点击的方法
2015/03/17 Javascript
JavaScript字符串对象(string)基本用法示例
2017/01/18 Javascript
JQuery 进入页面默认给已赋值的复选框打钩
2017/03/23 jQuery
微信小程序录音与播放录音功能
2017/12/25 Javascript
js 图片转base64的方式(两种)
2018/04/24 Javascript
JS实现字符串中去除指定子字符串方法分析
2018/05/17 Javascript
Vue实例的对象参数options的几个常用选项详解
2019/11/08 Javascript
js+css实现全屏侧边栏
2020/06/16 Javascript
[03:31]DOTA2英雄基础教程 大地之灵
2013/12/17 DOTA
Python中的字符串查找操作方法总结
2016/06/27 Python
Python SQLite3数据库日期与时间常见函数用法分析
2017/08/14 Python
Python设计模式之装饰模式实例详解
2019/01/21 Python
python替换字符串中的子串图文步骤
2019/06/19 Python
python中metaclass原理与用法详解
2019/06/25 Python
详解Python可视化神器Yellowbrick使用
2019/11/11 Python
python3 pathlib库Path类方法总结
2019/12/26 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
Python编写单元测试代码实例
2020/09/10 Python
HTML5所有标签汇总及标签意义解释
2015/03/12 HTML / CSS
HTML5实现文件断点续传的方法
2017/01/04 HTML / CSS
美国体育用品商店:Paragon Sports
2017/10/08 全球购物
蛋白质世界:Protein World
2017/11/23 全球购物
杭州龙健科技笔试题.net部分笔试题
2016/01/24 面试题
酒店员工检讨书
2014/02/18 职场文书
明星邀请函
2015/02/02 职场文书
绍兴鲁迅故居导游词
2015/02/09 职场文书
冰峪沟导游词
2015/02/09 职场文书
2015年清明节扫墓演讲稿
2015/03/18 职场文书
2015仓库保管员年终工作总结
2015/05/13 职场文书
Python的代理类实现,控制访问和修改属性的权限你都了解吗
2022/03/21 Python