/*工作单元

这个模式涉及到了领域模型、数据映射器和标识映射,这里就统一进行整理和回顾了。

$venue = new woodomainVenue(null,"The Green Tree");

woodomainObjectWatcher::instance()->performOperations();

现在以上面的二行客户端代码为切入点大概的叙述一下这个模式是怎么工作的。

第一句在使用领域模型对象创建一个对象的时候,它就调用了标识映射ObjectWatcher类

将自己标记为一个需要新增的对象。第二句的performOperations方法将保存在标识映射器的属性$new中的对象

插入到了数据库中。注意它内部调用的$obj->finder()方法是领域模式中通过HelperFactory工厂类生成一个相对应的数据映射器类并return过来。

HelperFactory这个类下面没有具体实现(原文也没有实现),其实就是根据参数传入的类的类型使用条件分支创建对应的数据映射器。

下面直接看代码和注释进行理解。*/namespace woodomain;//标识映射

classObjectWatcher{private $all = array(); //存放对象的小仓库

private $dirty = array(); //存放需要在数据库中修改的对象

private $new = array(); //存放需要在数据库中新增的对象

private $delete = array(); //存放需要在数据库中删除的对象

private static $instance; //单例

private function__construct (){}static functioninstance(){if(!self::$instance){

self::$instance = newObjectWatcher();

}return self::$instance;

}//获取一个唯一的标识,这里采用了领域类类名+ID的方式创建一个唯一标识,避免多个数据库表调用这个类时出现ID重复的问题

function globalKey(DomainObject $obj){$key = get_class($obj) . "." . $obj->getId();return $key;

}//添加对象

static function add(DomainObject $obj){$inst = self::instance();$inst->all[$inst->globalKey($obj)] = $obj;

}//获取对象

static function exists($classname,$id){$inst = self::instance();$key = "$classname.$id";if(isset($inst->all[$key]){return $inst->all[$key];

}return null;

}//标记为需要删除的对象

static function addDelete(DomainObject $obj){$self = self::instance();$self->delete[$self->globalKey($obj)] = $obj;

}//标记为需要修改的对象

static function addDirty(DomainObject $obj){$inst = self::instance();if(!in_array($obj,$inst->new,true)){$inst->dirty[$inst->globalKey($obj)] = $obj;

}

}//标记为需要新增的对象

static function addNew(DomainObject $obj){$inst = self::instance();$inst->new[] = $obj;

}//标记为干净的对象

static function addClean(DomainObject $obj){$self = self::instance();unset($self->delete[$self->globalKey($obj)]);unset($self->dirty[$self->globalKey($obj)]);$self->new = array_filter($self->new,function($a) use($obj) {return !($a === $obj);});

}//将上述需要增删改的对象与数据库交互进行处理

functionperformOperations(){foreach($this->dirty as $key=>$obj){$obj->finder()->update($obj); //$obj->finder()获取一个数据映射器

}foreach($this->new as $key=>$obj){$obj->finder()->insert($obj);

}$this->dirty = array();$this->new = array();

}

}//领域模型

abstract class DomainObject{ //抽象基类

private $id = -1;function __construct ($id=null){if(is_null($id)){$this->markNew(); //初始化时即被标记为需要新增的对象了

} else{$this->id = $id;

}

}//调用了标识映射的标记对象的方法

functionmarkNew(){

ObjectWatcher::addNew($this);

}functionmarkDeleted(){

ObjectWatcher::addDelete($this);

}functionmarkDirty(){

ObjectWatcher::addDirty($this);

}functionmarkClean(){

ObjectWatcher::addClean($this);

}function setId($id){$this->id = $id;

}functiongetId(){return $this->id;

}functionfinder(){return self::getFinder(get_class($this));

}//通过工厂类来实例化一个特定类型的数据映射器对象,例如VenueMapper

//这个对象将被标识映射器中的performOperations方法调用用于与数据库交互进行增删改的操作

static function getFinder($type){return HelperFactory::getFinder($type);

}

}class Venue extendsDomainObject {private $name;private $spaces;function __construct ($id = null,$name=null){$this->name= $name;$this->spaces = self::getCollection('\woo\domain\space');

parent::__construct($id);

}function setSpaces(SpaceCollection $spaces){$this->spaces = $spaces;$this->markDirty(); //标记为需要修改的对象

}function addSpace(Space $space){$this->spaces->add($space);$space->setVenue($this);$this->markDirty(); //标记为需要修改的对象

}function setName($name_s){$this->name = $name_s;$this->markDirty(); //标记为需要修改的对象

}functiongetName(){return $this->name;

}

}//领域模型

class Space extendsDomainObject{//.........

function setName($name_s){$this->name = $name_s;$this->markDirty();

}function setVenue(Venue $venue){$this->venue = $venue;$this->markDirty();

}

}//数据映射器

abstract classMapper{abstract static $PDO; //操作数据库的pdo对象

function__construct (){if(!isset(self::$PDO){$dsn = woobaseApplicationRegistry::getDSN();if(is_null($dsn)){throw new woobaseAppException("no dns");

}

self::$PDO = new PDO($dsn);

self::$PDO->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

}

}//获取标记的对象

private function getFroMap($id){return woodomainObjectWatcher::exists($this->targetClass(),$id);

}//新增标记的对象

private function addToMap(woodomainDomainObject $obj){//

return woodomainObjectWatcher::add($obj);

}//将数据库数据映射为对象

function createObject($array){$old = $this->getFromMap($array['id']);if($old){return $old;}$obj = $this->doCreateObject($array);$this->addToMap($obj);$obj->markClean();return $obj;

}function find($id){ //通过ID从数据库中获取一条数据并创建为对象

$old = $this->getFromMap($id);if($old){return $old}$this->selectStmt()->execute(array($id));$array= $this->selectStmt()->fetch();$this->selectStmt()->closeCursor();if(!is_array($array)){return null;

}if(!isset($array['id'])){return null;

}$object = $this->createObject($array);$this->addToMap($object);return $object;

}function insert(woodomainDomainObject $obj){ //将对象数据插入数据库

$this->doInsert($obj);$this->addToMap($obj);

}//需要在子类中实现的各个抽象方法

abstract function targetClass(); //获取类的类型

abstract function update(woodomainDomainObject $objet); //修改操作

protected abstract function doCreateObject(array $array); //创建对象

protected abstract function selectStmt(); //查询操作

protected abstract function doInsert(woodomainDomainObject $object); //插入操作

}class VenueMapper extendsMapper {function__construct (){

parent::__construct();//预处理对象

$this->selectStmt = self::$PDO->prepare("select * from venue where id=?");$this->updateStmt = self::$PDO->prepare("update venue set name=?,id=? where id=?");$this->insertStmt = self::$PDO->prepare("insert into venue (name) values(?)");

}protected function getCollection(array $raw){ //将Space数组转换成对象集合

return new SpaceCollection($raw,$this);

}protected function doCreateObject (array $array){ //创建对象

$obj = new woodomainVenue($array['id']);$obj->setname($array['name']);return $obj;

}protected function doInsert(woodomainDomainObject $object){ //将对象插入数据库

print 'inserting';debug_print_backtrace();$values = array($object->getName());$this->insertStmt->execute($values);$id = self::$PDO->lastInsertId();$object->setId($id);

}function update(woodomainDomainObject $object){ //修改数据库数据

print "updationn";$values = array($object->getName(),$object->getId(),$object->getId());$this->updateStmt->execute($values);

}function selectStmt(){ //返回一个预处理对象

return $this->selectStmt;

}

}//客户端

$venue = new woodomainVenue(null,"The Green Tree"); //在初始化时就被标记为新增对象了

$venue->addSpace(new woodomainSpace(null,"The Space Upstairs")); //这二行addSpace方法因为venue已经被标记新增所以不会再标记为修改对象,但是space在初始化的时候会被标记为新增对象

$venue->addSpace(new woodomainSpace(null,"The Bar Stage"));

woodomainObjectWatcher::instance()->performOperations(); //与数据库交互新增一条Venue数据,以及二条space数据

工作单元php,PHP面向对象之工作单元相关推荐

  1. Excel如何将工作表按照表内某一单元格命名

    今天跟大家分享一下Excel如何将工作表按照表内某一单元格命名 1.如下图我们想要按照工作表A1单元格内容命名工作表. 2.首先我们点击下图选项(Excel工具箱,百度即可了解详细的下载安装信息,本文 ...

  2. Excel技能培训-INDIRECT实现拼接动态引用单元格,trl+pageDown速切换工作簿,多工作表求和,多个工作簿合并和拆分

    1. 使用INDIRECT实现拼接动态引用单元格内容 =INDIRECT("E"&COUNTA(G14:G17)) 2. 使用ctrl+pageUp ,ctrl+pageD ...

  3. 发声单元的原理/扬声器的工作原理

    目前市面上常见的耳塞以及耳机的发声单元主要有三种,分别是动圈单元.动铁单元和静电单元.静电单元由于工艺比较复杂.成本高,单元本身比较脆弱,所以市面上并不多见.所以下面着重介绍动圈单元和动铁单元的发声原 ...

  4. 5.1 在工作表中查找指定内容的单元格 [原创Excel教程]

    1. 本节课将为您演示查找功能的使用,使用查找功能可以根据需要查找的内容,快速定位包含查找内容的单元格.首先点击[查找和选择]按钮,打开命令菜单. 2. 然后选择列表中的[查找]命令,打开查找和替换窗 ...

  5. Excel单元格中引用当前工作表名称

    有多份Excel表格表头标题都为"××学校第1次拉练考试××班成绩表",由于工作表结构都是一样的,所以我每次都是复制工作表然后编辑修改表中的数据.但经常是表中数据修改了,表头标题中 ...

  6. Excel工作表中设置好公式的单元格内容,不允许修改,如何锁定?

    Excel工作表中设置好公式的单元格内容,不允许修改,如何锁定? 目录 Excel工作表中设置好公式的单元格内容,不允许修改,如何锁定? 1.例如:我们做表格时已经设置好公式,只允许填写数据,不允许修 ...

  7. 计算机所选区域单元格数值,计算机习题110、 在Excel工作表的单元格区域A1:A8各单元格中均存放数值1,单元格A9为空,单元格A10为一字符...

    计算机习题110. 在Excel工作表的单元格区域A1:A8各单元格中均存放数值1,单元格A9为空,单元格A10为一字符 计算机习题1 10. 在Excel工作表的单元格区域A1:A8各单元格中均存放 ...

  8. 多个工作表同时处理+选中不连续的单元格和工作表

    一.多张工作表同时选中处理 1.单击第一张工作表+shift+单击最后一张工作表 或者直接单击右键选择  选中所有工作表 二.选择不连续工作表 选中其中一个工作表+ctrl+其他需要选中的工作表 转载 ...

  9. 面向对象第四单元小结

    面向对象第四单元:UML类图.顺序图.状态图 一.架构设计 第一次作业      第四单元第一次作业,需要完成的任务为实现一个UML类图解析器UmlInteraction,学习目标为UML入门级的理解 ...

最新文章

  1. 学习笔记之Linux Shell脚本教程:30分钟玩转Shell脚本编程
  2. 如何 循环 字母 php,PHP-php循环打印a-z字母的疑惑
  3. java工程如何跑起来的_你编写的Java代码是咋跑起来的?
  4. php mysql_fetch_array 不要0_1_php – mysql_fetch_array不适用于1行查询结果
  5. 严防ARP病毒的六个步骤
  6. mpls 保留标签值_浅析MPLS多协议标签交换的发展历程
  7. EMC变得更有中国味儿
  8. memcached可视化客户端工具
  9. javascript:访问iframe中的js函数
  10. 2021-08-30二叉树后向遍历 leetcode 栈
  11. 如何使Adobe Reader看PDF时的背景变为保护眼睛的绿色
  12. Onvif协议:IPC客户端开发之图像抓拍
  13. 互补滤波系数_四元数+互补滤波
  14. 怎么用PHP实现检测网站文章是否被收录
  15. 04-读取Word文档内容
  16. 风帆头,旗帜服,“背”在肩上的古国王印
  17. C++ 类成员函数指针的使用方法
  18. 开源CRM+SaaS云服务的生态模式能否撬动中国管理软件市场?
  19. 激活各种win 10 系统的方式
  20. png mat 转 osg

热门文章

  1. 幂函数与指数函数的区别
  2. 树莓派 ubuntu 安装Python+OpenCV
  3. sku属性组合小例子
  4. opencv光流Optical Flow
  5. http://blog.csdn.net/chrisniu1984/article/details/12050951
  6. 57 第一个Celery程序
  7. Day 13 老师应该要让课堂有趣吗
  8. dell服务器 win7系统安装教程,dell官方win7系统64位系统安装教程
  9. 宁波计算机软考培训机构,浙江宁波2019年下半年软考通过率约为25.7%
  10. mysql load xml_MySQL的SQL语句 - 数据操作语句(10)- LOAD XML 语句