设计模式专题(二十四) ——访问者模式

时间:2022-05-03
本文章向大家介绍设计模式专题(二十四) ——访问者模式,主要内容包括设计模式专题(二十三) ——解释器模式、设计模式专题(二十二) ——享元模式、设计模式专题(二十一) ——中介者模式、设计模式专题(二十) ——职责链模式、设计模式专题(十九) ——命令模式、设计模式专题(十八) ——桥接模式、设计模式专题(十七) ——单例模式、设计模式专题(十六)——迭代器模式、设计模式专题(十五) ——组合模式、设计模式专题(十四)——适配器模式、设计模式专题(十三) ——备忘录模式、设计模式专题(十二)——状态模式、设计模式专题(十一)——抽象工厂模式、设计模式专题(十)——观察者模式、设计模式专题(九) ——外观模式、设计模式专题(八) ——模板方法模式、设计模式专题(七)——建造者模式、设计模式专题(六)——原型模式、设计模式专题(五)——工厂方法模式、设计模式专题(四)——代理模式、设计模式专题(三)——装饰模式、设计模式专题(二)——策略模式、设计模式专题(一)——面向对象的设计原则、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

设计模式专题(二十四)——访问者模式

(原创内容,转载请注明来源,谢谢)

一、概述

访问者模式(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

相关阅读:

设计模式专题(二十三) ——解释器模式

设计模式专题(二十二) ——享元模式

设计模式专题(二十一) ——中介者模式

设计模式专题(二十) ——职责链模式

设计模式专题(十九) ——命令模式

设计模式专题(十八) ——桥接模式

设计模式专题(十七) ——单例模式

设计模式专题(十六)——迭代器模式

设计模式专题(十五) ——组合模式

设计模式专题(十四)——适配器模式

设计模式专题(十三) ——备忘录模式

设计模式专题(十二)——状态模式

设计模式专题(十一)——抽象工厂模式

设计模式专题(十)——观察者模式

设计模式专题(九) ——外观模式

设计模式专题(八) ——模板方法模式

设计模式专题(七)——建造者模式

设计模式专题(六)——原型模式

设计模式专题(五)——工厂方法模式

设计模式专题(四)——代理模式

设计模式专题(三)——装饰模式

设计模式专题(二)——策略模式

设计模式专题(一)——面向对象的设计原则