浅析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 相关文章推荐
最简单的PHP程序--记数器
Oct 09 PHP
用PHPdig打造属于你自己的Google[图文教程]
Feb 14 PHP
使用php重新实现PHP脚本引擎内置函数
Mar 06 PHP
PHP自动选择 连接本地还是远程数据库
Dec 02 PHP
php cookies中删除的一般赋值方法
May 07 PHP
浅析php面向对象public private protected 访问修饰符
Jun 30 PHP
使用PHP编写的SVN类
Jul 18 PHP
thinkphp控制器调度使用示例
Feb 24 PHP
PHP中数据类型转换的三种方式
Apr 02 PHP
Yii2.0表关联查询实例分析
Jul 18 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
Jul 22 PHP
PHP使用观察者模式处理异常信息的方法详解
Sep 24 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
最贵的咖啡是怎么产生的,它的风味怎么样?
2021/03/04 新手入门
PHP 源代码压缩小工具
2009/12/22 PHP
PHP实现递归复制整个文件夹的类实例
2015/08/03 PHP
php轻量级的性能分析工具xhprof的安装使用
2015/08/12 PHP
Yii2增加验证码步骤详解
2016/04/25 PHP
php头像上传预览实例代码
2017/05/02 PHP
php empty 函数判断结果为空但实际值却为非空的原因解析
2018/05/28 PHP
JSON 编辑器实现代码
2009/12/06 Javascript
禁止js文件缓存的代码
2010/04/09 Javascript
Javascript 去除数组的重复元素
2010/05/04 Javascript
javascript 判断中文字符长度的函数代码
2012/08/27 Javascript
jquery iframe操作详细解析
2013/11/20 Javascript
JS根据变量保存方法名并执行方法示例
2014/04/04 Javascript
javascript监听鼠标滚轮事件浅析
2014/06/05 Javascript
AngularJS基础知识
2014/12/21 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
jQuery 获取遍历获取table中每一个tr中的第一个td的方法
2016/10/05 Javascript
canvas红包照片实例分享
2017/02/28 Javascript
利用JS实现简单的瀑布流加载图片效果
2017/04/22 Javascript
基于vue.js的分页插件详解
2017/11/27 Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
2018/08/11 Javascript
laydate时间日历插件使用方法详解
2018/11/14 Javascript
vue 表单输入框不支持focus及blur事件的解决方案
2020/11/17 Vue.js
详解Vue3.0 + TypeScript + Vite初体验
2021/02/22 Vue.js
pycharm+django创建一个搜索网页实例代码
2018/01/24 Python
使用python将请求的requests headers参数格式化方法
2019/01/02 Python
美国电视购物:QVC
2017/02/06 全球购物
乐天旅游香港网站:日本饭店预订
2017/11/29 全球购物
德国亚洲食品网上商店:asiafoodland.de
2019/12/28 全球购物
结婚喜宴家长答谢词
2014/01/15 职场文书
婚内房产协议书范本
2014/10/02 职场文书
市贸粮局召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
新生开学寄语大全
2015/05/28 职场文书
中秋节随笔
2015/08/15 职场文书
2019最新企业员工考勤管理制度(通用版)!
2019/07/02 职场文书
CSS实现单选折叠菜单功能
2021/11/01 HTML / CSS