[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包分离开来。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 农村老人走丢了怎么办 读在职博士工作单位不支持怎么办 两证合一后国税怎么办 杭州的发票丢了怎么办 小车登记证丢了怎么办 个体户地税逾期未申报怎么办 公司社保本丢了怎么办 社保红本子掉了怎么办 三证合一后逾期怎么办 个体执照没办国税地税怎么办 丰巢APP注册没工牌号怎么办 农业银行k宝证书过期怎么办 个体户网上申报税没定期怎么办 遇到不给开票的商户怎么办 奶茶店电脑下单怎么办 个体户营业执照注销怎么办清税业务 注册公司没有办公地点怎么办 变更莒业执照法人怎么办手续 欠了几十万贷款怎么办 杭州公司跨区迁址怎么办 公司同市内跨区迁址怎么办 合同写错了字怎么办 农行卡转工行卡怎么办 外地人在北京交社保退休怎么办 身份证掉了单位宿舍怎么办居住证 广州租住单位宿舍怎么办居住证 公司u盾丢了怎么办 北京办了居住卡怎么办延期 商铺被陌生人注册左公司怎么办 营业执照年检登录密码忘了怎么办 欠人家钱没钱还怎么办 欠钱实在没钱还怎么办 党关系丢了10年怎么办? 离婚后生孩子怎么办出生证明 注册公司没有注册地址怎么办 银行流水不够2倍怎么办 个体户小店怎么办五险 姓和名五行相克怎么办? 三星s7刷机后计算器没有了怎么办 线雕鼻子山根鼓怎么办 在日本没有日币怎么办