首页 >后端开发 >php教程 >[php]Collection跟持久化工厂

[php]Collection跟持久化工厂

WBOY
WBOY原创
2016-06-13 11:37:50939浏览

[php]Collection和持久化工厂

        Mapper类中的findById($id)可以从数据库中取出指定id的一条数据,映射成一个对象返回。很多时候我们需要返回一个数据集合(findAll),那我们就需要一种数据结构来保存这些数据,在需要时映射成对象。既然一条数据映射成一个对象,那么一个数据集合就需要一个对象集合。可以把数据集合和对象集合放在一个类中,这样就方便处理数据到对象的映射了。我们把这个类命名为Collection,为了能更好好的访问集合对象,Collection子类都实现了Iterator接口,使用foreach可以方便访问。

       Collection的类结构:

                                          

        \demo\mapper\Collection: 

namespace demo\mapper;use demo\base\AppException;use demo\domain\DomainObject;use demo\mapper\Mapper;abstract class Collection {	// 保存数据库取出的行数据	protected $raws;	// 保存已映射的对象	protected $objects = array();	// 用于$raws[]到$objects的映射	protected $mapper;	// 当前指针	private $pointer = 0;	// 对象数组总数	private $total = 0;		/**	 * @param array $raws 未处理过的数据库数据	 * @param Mapper $mapper 用于把$raws映射成对象(createObject)	 */	public function __construct(array $raws = null, Mapper $mapper = null) {		if (!is_null($raws) && !is_null($mapper)) {			$this->raws = $raws;			$this->total = count($raws);		}				$this->mapper = $mapper;	}		/**	 * 返回指定$num的数据对象	 * @param int $num	 */	public function getRow($num) {		if ($num = $this->total) {			return null;		}				// 延迟加载		$this->notifyAccess();				if (isset($this->objects[$num])) {			return $this->objects[$num];		}				if (isset($this->raws[$num])) {			$obj = $this->mapper->createObject($this->raws[$num]);			$this->objects[$num] = $obj;			return $obj;		}				return null;	}		/**	 * 添加对象	 * @param DomainObject $obj	 * @throws AppException	 */	public function add(DomainObject $obj) {		// 类型安全检查		$targetClass = $this->getTargetClass();		if (!($obj instanceof $targetClass)) {			throw new AppException("Object must be {$targetClass}");		}				// 		$this->notifyAccess();		$this->objects[$this->pointer++] = $obj;	}		public function current() {		return $this->getRow($this->pointer);	}		public function next() {		$obj = $this->getRow($this->pointer);		if (!is_null($obj)) {			$this->pointer++;		}				return $obj;	}		public function key() {		return $this->pointer;	}		public function rewind() {		$this->pointer = 0;	}		public function valid() {		return !is_null($this->current());	}		/**	 * 延迟加载	 */	protected  function notifyAccess() {		// 暂时留空	}		protected abstract function getTargetClass();}

        \demo\domain:

namespace demo\domain;use \demo\domain\DomainObject;interface ClassroomCollection extends \Iterator {	public function add(DomainObject $obj);}interface StudentCollection extends \Iterator {	public function add(DomainObject $obj);}interface ScoreCollection extends \Iterator {	public function add(DomainObject $obj);}
        \demo\mapper:
namespace demo\mapper;class ClassroomCollection extends Collection 		implements \demo\domain\ClassroomCollection {		protected function getTargetClass() {		return '\demo\domain\Classroom';	}}class StudentCollection extends Collection 		implements \demo\domain\StudentCollection {		protected function getTargetClass() {		return '\demo\domain\Student';	}}class ScoreCollection extends Collection 		implements \demo\domain\ScoreCollection {	protected function getTargetClass() {		return '\demo\domain\Score';	}}
        为什么需要为domain包还需要一个Collection接口呢?因为domain包需要用到Collection来保存数据,为了让domain包不依赖于mapper包的Collection,所以创建了一个接口。而\demo\domain\mapper\Collection则会实现这个接口。

         现在的结构开始有点复杂了,为了能管理好Mapper和Collection的具体子类,我们可以使用抽象工厂来管理对象的创建。来看看类图:

                                           

        \demo\mapper\PersistanceFatory

namespace demo\mapper;/** * 持久化工厂 */abstract class PersistanceFactory {		public static function getFactory($targetClass) {		switch ($targetClass) {			case '\demo\domain\Classroom':				return new ClassroomPersistanceFactory();							case '\demo\domain\Student':				return new StudentPersistanceFactory();							case '\demo\domain\Score':				return new ScorePersistanceFactory();		}	}		public abstract function getMapper();		public abstract function getCollection(array $raws = null);}class ClassroomPersistanceFactory extends PersistanceFactory {	public function getMapper() {		return new ClassroomMapper();	}		public function getCollection(array $raws = null) {		return new ClassroomCollection($raws, $this->getMapper());	}}class StudentPersistanceFactory extends PersistanceFactory {	public function getMapper() {		return new StudentMapper();	}		public function getCollection(array $raws = null) {		return new StudentCollection($raws, $this->getMapper());	}}class ScorePersistanceFactory extends PersistanceFactory {	public function getMapper() {		return new ScoreMapper();	}		public function getCollection(array $raws = null) {		return new ScoreCollection($raws, $this->getMapper());	}}
        使用这样的工厂模式可以很方便地创建指定的Mapper和Collection子类了,同时这种方式也可以方便以后新功能的添加。

        domain包中同样需要Collection对象,但需要注意和mapper中的Collection分离开来。我们可以在domain包中创一个HelperFactory类来当做domain访问mapper的桥梁。

                                                              

namespace demo\domain;use demo\mapper\PersistanceFactory;class HelperFactory {		public static function getCollection($targetClass) {		$fact = PersistanceFactory::getFactory($targetClass);		return $fact->getCollection();	}		public static function getFinder($targetClass) {		$fact = PersistanceFactory::getFactory($targetClass);		return $fact->getMapper();		}}

        这样就把domain包和mapper包分离开来了。


       Collection有了,那么就来实现Mapper的findAll()吧。

namespace demo\mapper;use demo\base\AppException;use \demo\base\ApplicationRegistry;/** * Mapper */abstract  class Mapper {		//...		/**	 * 返回Collection	 */	public function findAll() {		$pStmt = $this->getSelectAllStmt();		$pStmt->execute(array());		$raws = $pStmt->fetchAll(\PDO::FETCH_ASSOC);		$collection = $this->getCollection($raws);				return $collection;	}		/**	 * 返回子类Collection	 * @param array $raw	 */	public function getCollection(array $raws) {		return $this->getFactory()->getCollection($raws);	}		/**	 * 返回子类持久化工厂对象	 */	public function getFactory() {		return PersistanceFactory::getFactory($this->getTargetClass());			}		//....}

         例子:

$fact = PersistanceFactory::getFactory('\demo\domain\Classroom');$mapper = $fact->getMapper();$classrooms = $mapper->findAll();foreach ($classrooms as $elem) {	var_dump($elem);}

        Colletion能方便管理$raws[]到$objects[]的映射。
        PersistanceFactory能管理好mapper包中类对象的创建。
        HelperFactory把mapper包和domain包分离开来。

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn