PHP面向对象之工作单元(实例讲解)
工作单元
这个模式涉及到了领域模型、数据映射器和标识映射,这里就统一进行整理和回顾了。
$venue=new\woo\domain\Venue(null,"TheGreenTree");
\woo\domain\ObjectWatcher::instance()->performOperations();
现在以上面的二行客户端代码为切入点大概的叙述一下这个模式是怎么工作的。
第一句在使用领域模型对象创建一个对象的时候,它就调用了标识映射ObjectWatcher类
将自己标记为一个需要新增的对象。第二句的performOperations方法将保存在标识映射器的属性$new中的对象
插入到了数据库中。注意它内部调用的$obj->finder()方法是领域模式中通过HelperFactory工厂类生成一个相对应的数据映射器类并return过来。
HelperFactory这个类下面没有具体实现(原文也没有实现),其实就是根据参数传入的类的类型使用条件分支创建对应的数据映射器。
下面直接看代码和注释进行理解。
namespacewoo\domain; //标识映射 classObjectWatcher{ private$all=array();//存放对象的小仓库 private$dirty=array();//存放需要在数据库中修改的对象 private$new=array();//存放需要在数据库中新增的对象 private$delete=array();//存放需要在数据库中删除的对象 privatestatic$instance;//单例 privatefunction__construct(){} staticfunctioninstance(){ if(!self::$instance){ self::$instance=newObjectWatcher(); } returnself::$instance; } //获取一个唯一的标识,这里采用了领域类类名+ID的方式创建一个唯一标识,避免多个数据库表调用这个类时出现ID重复的问题 functionglobalKey(DomainObject$obj){ $key=get_class($obj).".".$obj->getId(); return$key; } //添加对象 staticfunctionadd(DomainObject$obj){ $inst=self::instance(); $inst->all[$inst->globalKey($obj)]=$obj; } //获取对象 staticfunctionexists($classname,$id){ $inst=self::instance(); $key="$classname.$id"; if(isset($inst->all[$key]){ return$inst->all[$key]; } returnnull; } //标记为需要删除的对象 staticfunctionaddDelete(DomainObject$obj){ $self=self::instance(); $self->delete[$self->globalKey($obj)]=$obj; } //标记为需要修改的对象 staticfunctionaddDirty(DomainObject$obj){ $inst=self::instance(); if(!in_array($obj,$inst->new,true)){ $inst->dirty[$inst->globalKey($obj)]=$obj; } } //标记为需要新增的对象 staticfunctionaddNew(DomainObject$obj){ $inst=self::instance(); $inst->new[]=$obj; } //标记为干净的对象 staticfunctionaddClean(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->dirtyas$key=>$obj){ $obj->finder()->update($obj);//$obj->finder()获取一个数据映射器 } foreach($this->newas$key=>$obj){ $obj->finder()->insert($obj); } $this->dirty=array(); $this->new=array(); } } //领域模型 abstractclassDomainObject{//抽象基类 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); } functionsetId($id){ $this->id=$id; } functiongetId(){ return$this->id; } functionfinder(){ returnself::getFinder(get_class($this)); } //通过工厂类来实例化一个特定类型的数据映射器对象,例如VenueMapper //这个对象将被标识映射器中的performOperations方法调用用于与数据库交互进行增删改的操作 staticfunctiongetFinder($type){ returnHelperFactory::getFinder($type); } } classVenueextendsDomainObject{ private$name; private$spaces; function__construct($id=null,$name=null){ $this->name=$name; $this->spaces=self::getCollection('\\woo\\domain\\space'); parent::__construct($id); } functionsetSpaces(SpaceCollection$spaces){ $this->spaces=$spaces; $this->markDirty();//标记为需要修改的对象 } functionaddSpace(Space$space){ $this->spaces->add($space); $space->setVenue($this); $this->markDirty();//标记为需要修改的对象 } functionsetName($name_s){ $this->name=$name_s; $this->markDirty();//标记为需要修改的对象 } functiongetName(){ return$this->name; } } //领域模型 classSpaceextendsDomainObject{ //......... functionsetName($name_s){ $this->name=$name_s; $this->markDirty(); } functionsetVenue(Venue$venue){ $this->venue=$venue; $this->markDirty(); } } //数据映射器 abstractclassMapper{ abstractstatic$PDO;//操作数据库的pdo对象 function__construct(){ if(!isset(self::$PDO){ $dsn=\woo\base\ApplicationRegistry::getDSN(); if(is_null($dsn)){ thrownew\woo\base\AppException("nodns"); } self::$PDO=new\PDO($dsn); self::$PDO->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); } } //获取标记的对象 privatefunctiongetFroMap($id){ return\woo\domain\ObjectWatcher::exists($this->targetClass(),$id); } //新增标记的对象 privatefunctionaddToMap(\woo\domain\DomainObject$obj){////// return\woo\domain\ObjectWatcher::add($obj); } //将数据库数据映射为对象 functioncreateObject($array){ $old=$this->getFromMap($array['id']); if($old){return$old;} $obj=$this->doCreateObject($array); $this->addToMap($obj); $obj->markClean(); return$obj; } functionfind($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)){ returnnull; } if(!isset($array['id'])){ returnnull; } $object=$this->createObject($array); $this->addToMap($object); return$object; } functioninsert(\woo\domain\DomainObject$obj){//将对象数据插入数据库 $this->doInsert($obj); $this->addToMap($obj); } //需要在子类中实现的各个抽象方法 abstractfunctiontargetClass();//获取类的类型 abstractfunctionupdate(\woo\domain\DomainObject$objet);//修改操作 protectedabstractfunctiondoCreateObject(array$array);//创建对象 protectedabstractfunctionselectStmt();//查询操作 protectedabstractfunctiondoInsert(\woo\domain\DomainObject$object);//插入操作 } classVenueMapperextendsMapper{ function__construct(){ parent::__construct(); //预处理对象 $this->selectStmt=self::$PDO->prepare("select*fromvenuewhereid=?"); $this->updateStmt=self::$PDO->prepare("updatevenuesetname=?,id=?whereid=?"); $this->insertStmt=self::$PDO->prepare("insertintovenue(name)values(?)"); } protectedfunctiongetCollection(array$raw){//将Space数组转换成对象集合 returnnewSpaceCollection($raw,$this); } protectedfunctiondoCreateObject(array$array){//创建对象 $obj=new\woo\domain\Venue($array['id']); $obj->setname($array['name']); return$obj; } protectedfunctiondoInsert(\woo\domain\DomainObject$object){//将对象插入数据库 print'inserting'; debug_print_backtrace(); $values=array($object->getName()); $this->insertStmt->execute($values); $id=self::$PDO->lastInsertId(); $object->setId($id); } functionupdate(\woo\domain\DomainObject$object){//修改数据库数据 print"updation\n"; $values=array($object->getName(),$object->getId(),$object->getId()); $this->updateStmt->execute($values); } functionselectStmt(){//返回一个预处理对象 return$this->selectStmt; } } //客户端 $venue=new\woo\domain\Venue(null,"TheGreenTree");//在初始化时就被标记为新增对象了 $venue->addSpace(new\woo\domain\Space(null,"TheSpaceUpstairs"));//这二行addSpace方法因为venue已经被标记新增所以不会再标记为修改对象,但是space在初始化的时候会被标记为新增对象 $venue->addSpace(new\woo\domain\Space(null,"TheBarStage")); \woo\domain\ObjectWatcher::instance()->performOperations();//与数据库交互新增一条Venue数据,以及二条space数据
以上这篇PHP面向对象之工作单元(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。