浅析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 相关文章推荐
第十二节--类的自动加载
Nov 16 PHP
初级的用php写的采集程序
Mar 16 PHP
php getsiteurl()函数
Sep 05 PHP
php递归实现无限分类生成下拉列表的函数
Aug 08 PHP
探讨fckeditor在Php中的配置详解
Jun 08 PHP
php Imagick获取图片RGB颜色值
Jul 28 PHP
php过滤HTML标签、属性等正则表达式汇总
Sep 22 PHP
ThinkPHP上使用多说评论插件的方法
Oct 31 PHP
Yii数据库缓存实例分析
Mar 29 PHP
Yii2实现跨mysql数据库关联查询排序功能代码
Feb 10 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
Nov 23 PHP
laravel邮件发送的实现代码示例
Jan 31 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
Views rows style模板重写代码
2011/05/16 PHP
is_uploaded_file函数引发的不能上传文件问题
2013/10/29 PHP
使用PHP函数scandir排除特定目录
2014/06/12 PHP
PHP语法小结之基础和变量
2015/11/22 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
PHP迭代与递归实现无限级分类
2017/08/28 PHP
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
js+jquery常用知识点汇总
2015/03/03 Javascript
基于jquery实现省市联动特效
2015/12/17 Javascript
15位和18位身份证JS校验的简单实例
2016/07/18 Javascript
Javascript学习之谈谈JS的全局变量跟局部变量(推荐)
2016/08/28 Javascript
Node.js用readline模块实现输入输出
2016/12/16 Javascript
vue 框架下自定义滚动条(easyscroll)实现方法
2019/08/29 Javascript
sharp.js安装过程中遇到的问题总结
2020/04/02 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
微信小程序动态评分展示/五角星展示/半颗星展示/自定义长度展示功能的实现
2020/07/22 Javascript
JS实现放大镜效果
2020/09/21 Javascript
python多线程扫描端口示例
2014/01/16 Python
python3.3使用tkinter开发猜数字游戏示例
2014/03/14 Python
Python作用域用法实例详解
2016/03/15 Python
Python使用while循环花式打印乘法表
2019/01/28 Python
详解python运行三种方式
2019/05/13 Python
Python3从零开始搭建一个语音对话机器人的实现
2019/08/23 Python
Python+opencv+pyaudio实现带声音屏幕录制
2019/12/23 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
2020/02/04 Python
完美解决ARIMA模型中plot_acf画不出图的问题
2020/06/04 Python
Python Process创建进程的2种方法详解
2021/01/25 Python
html5 web本地存储将取代我们的cookie
2012/12/26 HTML / CSS
吃透移动端 1px的具体用法
2019/12/16 HTML / CSS
来自世界各地的优质葡萄酒:VineShop24
2018/07/09 全球购物
博朗(Braun)俄罗斯官方商店:德国小家电品牌
2019/09/24 全球购物
寄语是什么意思
2014/04/10 职场文书
人代会标语
2014/06/30 职场文书
2014年企业团支部工作总结
2014/12/10 职场文书
Python下载商品数据并连接数据库且保存数据
2022/03/31 Python
python使用BeautifulSoup 解析HTML
2022/04/24 Python