浅析PHP中Collection 类的设计

用.net开发已经很多年了,最近接触到PHP,发现PHP也很好玩。不过发现它里面没有集合Collection类,只有数组,并且数组很强。这里我用数组来包装成一个集合Collection,代码如下:
<div class="codetitle"><a style="CURSOR: pointer" data="69256" class="copybut" id="copybut69256" onclick="doCopy('code69256')"> 代码如下:

<div class="codebody" id="code69256">
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:
<div class="codetitle"><a style="CURSOR: pointer" data="60970" class="copybut" id="copybut60970" onclick="doCopy('code60970')"> 代码如下:
<div class="codebody" id="code60970">
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代码如下:
<div class="codetitle"><a style="CURSOR: pointer" data="38943" class="copybut" id="copybut38943" onclick="doCopy('code38943')"> 代码如下:
<div class="codebody" id="code38943">
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如下:
<div class="codetitle"><a style="CURSOR: pointer" data="78464" class="copybut" id="copybut78464" onclick="doCopy('code78464')"> 代码如下:<div class="codebody" id="code78464">
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,1);
$col->addItem(new Course(2,2);
}
}

调用代码如下:
$student=new Student(1,"majiang");
print $student->getName();
print $student->course->getItem(1);

CollectionPHP

相关文章

Hessian开源的远程通讯,采用二进制 RPC的协议,基于 HTTP 传输。可以实现PHP调用Java,Python,C#等多语...
初识Mongodb的一些总结,在Mac Os X下真实搭建mongodb环境,以及分享个Mongodb管理工具,学习期间一些总结...
边看边操作,这样才能记得牢,实践是检验真理的唯一标准.光看不练假把式,光练不看傻把式,边看边练真把式....
在php中,结果输出一共有两种方式:echo和print,下面将对两种方式做一个比较。 echo与print的区别: (...
在安装好wampServer后,一直没有使用phpMyAdmin,今天用了一下,phpMyAdmin显示错误:The mbstring exte...
变量是用于存储数据的容器,与代数相似,可以给变量赋予某个确定的值(例如:$x=3)或者是赋予其它的变...