[php]Collection和持久化工厂
来源:互联网 发布:医院ap网络 编辑:程序博客网 时间:2024/06/02 11:41
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 < 0 || $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包分离开来。
- [php]Collection和持久化工厂
- PHP-Collection类
- PHP Collection 类
- COllection介绍和Collection排序
- php持久登录
- 关于PHP持久化
- PHP持久问题
- shoi2001 化工厂装箱员
- php Collection类的设计
- Collection和Collection是的区别对比
- Collection和Collections区别
- Collection和Map
- Collection和Map接口
- Collection和Collections区别
- Collection和List区别
- Collection和map
- java--collection和Iterator
- Collections和Collection区别
- 简单二叉树的实现
- 字符串循环移位
- uva 10006 Carmichael Numbers(快速幂)
- 《C和指针》——第九章 判断回文
- 初识Objecive-C 之 内存管理
- [php]Collection和持久化工厂
- paip. erlang语法C++语法对比attilax总结
- 所见即所得:七大无需编程的DIY开发工具
- 装饰和继承的区别
- 数组与指针的区别
- Wireshark抓包工具使用教程以及常用抓包规则
- NSCoding协议
- OCP-1Z0-051-V9.02-125题
- 《深入理解Java虚拟机》笔记