日期:2014-05-17  浏览次数:20465 次

php Collection类的设计

用。net开发已经很多年了,最近接触到php,发现php也没好玩。不过发现它里面没有集合类,只有数组,并且数组很强。这里我用数组来包装成一个集合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) {
    $