设计模式专题(二十四) ——访问者模式
时间: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
相关阅读:
设计模式专题(二十三) ——解释器模式
设计模式专题(二十二) ——享元模式
设计模式专题(二十一) ——中介者模式
设计模式专题(二十) ——职责链模式
设计模式专题(十九) ——命令模式
设计模式专题(十八) ——桥接模式
设计模式专题(十七) ——单例模式
设计模式专题(十六)——迭代器模式
设计模式专题(十五) ——组合模式
设计模式专题(十四)——适配器模式
设计模式专题(十三) ——备忘录模式
设计模式专题(十二)——状态模式
设计模式专题(十一)——抽象工厂模式
设计模式专题(十)——观察者模式
设计模式专题(九) ——外观模式
设计模式专题(八) ——模板方法模式
设计模式专题(七)——建造者模式
设计模式专题(六)——原型模式
设计模式专题(五)——工厂方法模式
设计模式专题(四)——代理模式
设计模式专题(三)——装饰模式
设计模式专题(二)——策略模式
设计模式专题(一)——面向对象的设计原则
- 新浪微博爬虫最新分享
- Unity Application Block 3月12 发布的版本
- HTTPS静态服务搭建过程详解
- 基于Webkit的浏览器关键渲染路径介绍
- CodePlex 全面支持Subversion/TortoiseSVN
- 计算机程序的思维逻辑 (11) - 初识函数
- Android WebView 调试方法
- Python开发微信公众号后台(系列一)
- Consul最常用的命令和接口api
- webpack的Hot Module Replacement运行机制
- 如何使用Node.js编写命令工具——以vue-cli为例
- SpringBoot编写自定义的starter
- webpack3新特性简介
- Python机器学习算法入门之梯度下降法实现线性回归
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Cypress系列(60)- 运行时的截图和录屏
- 请停止使用Excel进行数据分析,升级到Python吧
- git版本控制器的相关操作
- 离线 Android Studio 环境
- Actor:人生如戏全靠演技--“三维度”逻辑编程语言的设计(3) 角色是一种特定的关系名不正言不顺角色才是真正的主人演员的天分再好的演技也需要角色好演员更需要好剧本
- 2.CSS选择器-CSS基础
- es6 随性学习之let,const与var的区别
- 04-操作文件和目录 遇到的坑
- 1.CSS单位-CSS进阶
- Geode集群搭建
- 2.CSS特性-CSS进阶
- 5.图片-HTML基础
- geode的安装部署
- 3.CSS优先级-CSS进阶
- docker的相关操作