设计模式专题(二十四)——访问者模式
(原创内容,转载请注明来源,谢谢)
一、概述
访问者模式(visitor)表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下,定义作用于这些元素的新操作。
访问者模式适用于数据结构相对稳定的系统,并把数据结构和作用于结构上的操作之间的耦合解开,使操作可以自由地演化。
访问者模式的目的是为了把处理从数据结构分离出来,如果有比较稳定的数据结构,易于变化的算法,则访问者模式比较合适。
访问者模式的优点在于增加新的操作很容易,意味着增加一个新的访问者,访问者模式将有关的行为集中到一个访问者对象中。
访问者模式的缺点在于增加新的数据结构很难,因为其设计的时候基本已经按照数据结构设定好了。
访问者模式使用了运行期间的执行,根据实际传入的类型执行其特定的方法,这个称为双分派技术(double dispatch)。
二、类图
三、设计实现
1、业务场景
现需要实现工作单元,将数据库中查询的内容,转换成一个类进行存储,而在查询后对该类进行的增删改操作,会等工作单元执行commit的时候一并提交,而期间会先计入缓存,这样既可以实现多个增删改操作一并提交,又能保证数据一致性。
2、实现过程
<?php
//访问者模式
//1.抽象element
abstract class Element{
protected$isDelete;
protected$isUpdate;
protected$isInsert;
protected$sql;
protected$data;
publicfunction __construct(){
$this->isDelete= false;
$this->isUpdate= false;
$this->isInsert= false;
$this->sql= '';
$this->data= array();
}
protectedfunction delete(){
$this->isDelete= true;
}
protectedfunction isUpdate(){
$this->isUpdate= true;
}
protectedfunction isInsert(){
$this->isInsert= true;
}
publicfunction getSql(){
return$this->sql;
}
publicfunction setData($type, $data){
switch($type) {
case'insert':
$this->isInsert();
$this->insert($data);
break;
case'update':
$this->isUpdate();
$this->update($data);
case'delete':
$this->isDelete();
$this->delete($data);
default:
$this->select($data);
break;
}
$this->data= $data;
}
publicfunction insert($data){}
publicfunction update($data){}
publicfunction delete($data){}
publicfunction select($data){}
}
//2.具体element--delete
class ElementTableA{
publicfunction __construct(){
parent::__construct();
}
publicfunction insert($data){
$this->sql= 'insert tableA的sql';
}
publicfunction update($data){
$this->sql= 'update tableA的sql';
}
publicfunction delete($data){
$this->sql= 'delete tableA的sql';
}
}
//table B 同 table A
//3.执行类
class UnitWork{
public$sqls;
public$elements;
privatefunction setElements(array $elements){
foreach($elements as $index => $ele) {
if(!($eleinstanceof Element)){
unset($elements[$index]);
}
}
if(empty($elements)){
returnfalse;
}
$this->elements= $elements;
returntrue;
}
privatefunction setSqls(){
foreach($this->elements as $element) {
if(empty($element->getSql())){
continue;
}
$this->sqls[]= $element->sql;
}
if(empty($this->sqls)){
returnfalse;
}
returntrue;
}
privatefunction run(){
//1.连接数据库
foreach($this->sqls as $sql) {
//2.执行sql
}
//3.断开数据库连接
}
publicfunction commit(array $elements){
if(empty($elements)){
returnfalse;
}
$res= $this->setElements($elements);
if(!$res){
returnfalse;
}
$res= $this->setSqls();
if(!$res){
returnfalse;
}
$this->run();
}
}
//4.客户端
$ea = new ElementTableA();
$ea->insert(array('col1'=>'a','col2'=>'b'));
$eb = new ElementTableA();
$eb->update(array('id'=>'xx','col1'=>'a', 'col2'=>'b'));
$uw = new UnitWork();
$uw->commit(array($ea, $eb));
——written by linhxx 2017.09.05
相关阅读: