Heim > Backend-Entwicklung > PHP-Tutorial > [php]Collection跟持久化工厂

[php]Collection跟持久化工厂

WBOY
Freigeben: 2016-06-13 12:35:21
Original
778 Leute haben es durchsucht

[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();
}
Nach dem Login kopieren

        \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);
}
Nach dem Login kopieren
        \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';
	}
}
Nach dem Login kopieren
        为什么需要为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());
	}
}
Nach dem Login kopieren
        使用这样的工厂模式可以很方便地创建指定的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();	
	}
}
Nach dem Login kopieren

        这样就把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());		
	}
	
	//....
}
Nach dem Login kopieren

         例子:

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

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

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage