浅析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将数据库中的电话号码读取出来并生成图片
Aug 31 PHP
php程序之die调试法 快速解决错误
Sep 17 PHP
打造超酷的PHP数据饼图效果实现代码
Nov 23 PHP
PHP提示Notice: Undefined variable的解决办法
Nov 24 PHP
PHP、Nginx、Apache中禁止网页被iframe引用的方法
Oct 01 PHP
PHP+MYSQL会员系统的开发实例教程
Aug 23 PHP
非常经典的PHP文件上传类分享
May 15 PHP
php mysql like 实现多关键词搜索的方法
Oct 29 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
Nov 14 PHP
阿里对象存储OSS在laravel框架中的使用方法
Oct 13 PHP
PHP实现发送微博消息功能完整示例
Dec 04 PHP
php框架知识点的整理和补充
Mar 01 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
老机欣赏|中国60年代精品收音机
2021/03/02 无线电
PHP+MySQL 制作简单的留言本
2009/11/02 PHP
php empty函数判断mysql表单是否为空
2010/04/12 PHP
PHP数组对比函数,存在交集则返回真,否则返回假
2011/02/03 PHP
php给一组指定关键词添加span标签的方法
2015/03/31 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
PHP进阶学习之Geo的地图定位算法详解
2019/06/19 PHP
BOOM vs RR BO5 第四场 2.14
2021/03/10 DOTA
JS拖动技术 关于setCapture使用
2010/12/09 Javascript
javascrpt绑定事件之匿名函数无法解除绑定问题
2012/12/06 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
jquery 实现上下滚动效果示例代码
2013/08/09 Javascript
JavaScript中instanceof运算符的用法总结
2013/11/19 Javascript
js数组操作常用方法
2014/05/08 Javascript
IE6 hack for js 集锦
2014/09/23 Javascript
js实现黑色简易的滑动门网页tab选项卡效果
2015/08/31 Javascript
深入理解jQuery.data() 的实现方式
2016/11/30 Javascript
JS实现的模仿QQ头像资料卡显示与隐藏效果
2017/04/07 Javascript
微信小程序 本地数据读取实例
2017/04/27 Javascript
日期时间范围选择插件:daterangepicker使用总结(必看篇)
2017/09/14 Javascript
javascript基于定时器实现进度条功能实例
2017/10/13 Javascript
如何在JavaScript中正确处理变量
2020/12/25 Javascript
玩转python爬虫之爬取糗事百科段子
2016/02/17 Python
Python对列表去重的多种方法(四种方法)
2017/12/05 Python
详谈Python 窗体(tkinter)表格数据(Treeview)
2018/10/11 Python
pytorch使用指定GPU训练的实例
2019/08/19 Python
Python udp网络程序实现发送、接收数据功能示例
2019/12/09 Python
pytorch 数据处理:定义自己的数据集合实例
2019/12/31 Python
解决Tensorboard 不显示计算图graph的问题
2020/02/15 Python
用CSS3来实现社交分享按钮
2014/11/11 HTML / CSS
html2 canvas生成清晰的图片实现打印功能
2019/09/23 HTML / CSS
美国演唱会和体育门票购买网站:Ticketnetwork
2018/10/19 全球购物
大学生励志演讲稿
2014/04/25 职场文书
财务会计专业求职信
2014/06/09 职场文书
2014年综合治理工作总结
2014/11/20 职场文书
2015暑期社会实践通讯稿
2015/07/18 职场文书