访问者模式是一种行为型模式,访问者表示一个作用于某对象结构中各元素的操作。它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者角色。

访问者模式利用了双重分派。先将访问者传入元素对象的Accept方法中,然后元素对象再将自己传入访问者,之后访问者执行元素的相应方法。

主要角色

抽象访问者角色(Visitor):为该对象结构(ObjectStructure)中的每一个具体元素提供一个访问操作接口。该操作接口的名字和参数标识了 要访问的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
具体访问者角色(ConcreteVisitor):实现抽象访问者角色接口中针对各个具体元素角色声明的操作。
抽象节点(Node)角色:该接口定义一个accept操作接受具体的访问者。
具体节点(Node)角色:实现抽象节点角色中的accept操作。
对象结构角色(ObjectStructure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合(在PHP中我们使用数组代替,因为PHP中的数组本来就是一个可以放置任何类型数据的集合)

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

interface ServiceVisitor
{
public function SendMsg(SendMessage $s);
function PushMsg(PushMessage $p);
} class AliYun implements ServiceVisitor
{
public function SendMsg(SendMessage $s)
{
echo '阿里云发送短信!', PHP_EOL;
}
public function PushMsg(PushMessage $p)
{
echo '阿里云推送信息!', PHP_EOL;
}
} class JiGuang implements ServiceVisitor
{
public function SendMsg(SendMessage $s)
{
echo '极光发送短信!', PHP_EOL;
}
public function PushMsg(PushMessage $p)
{
echo '极光推送短信!', PHP_EOL;
}
} interface Message
{
public function Msg(ServiceVisitor $v);
} class PushMessage implements Message
{
public function Msg(ServiceVisitor $v)
{
echo '推送脚本启动:';
$v->PushMsg($this);
}
} class SendMessage implements Message
{
public function Msg(ServiceVisitor $v)
{
echo '短信脚本启动:';
$v->SendMsg($this);
}
} class ObjectStructure
{
private $elements = []; public function Attach(Message $element)
{
$this->elements[] = $element;
} public function Detach(Message $element)
{
$position = 0;
foreach ($this->elements as $e) {
if ($e == $element) {
unset($this->elements[$position]);
break;
}
$position++;
}
} public function Accept(ServiceVisitor $visitor)
{
foreach ($this->elements as $e) {
$e->Msg($visitor);
}
} } $o = new ObjectStructure();
$o->Attach(new PushMessage());
$o->Attach(new SendMessage()); $v1 = new AliYun();
$v2 = new JiGuang(); $o->Accept($v1);
$o->Accept($v2);

  

23种模式总览 : https://www.cnblogs.com/houss/p/11121584.html

php 23种设计模型 - 访问者模式的更多相关文章

  1. php 23种设计模型 - 工厂模式

    工厂模式(Factory) 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建 ...

  2. php 23种设计模型 - 桥接模式

    桥接模式(Bridge) 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉 ...

  3. php 23种设计模型 - 状态模式

    状态模式 状态模式当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列 ...

  4. php 23种设计模型 - 模板方法模式

    模板模式 模板模式准备一个抽象类,将部分逻辑以具体方法以及具体构造形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.先制 ...

  5. php 23种设计模型 - 建造者模式

    建造者模式(Builder) 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 一个 Bu ...

  6. php 23种设计模型 - 原型模式

    原型模式(Prototype) 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现 ...

  7. php 23种设计模型 - 组合模式(合成模式)

    组合模式(Composite) 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这 ...

  8. php 23种设计模型 - 门面模式(外观模式)

    外观模式(Facade) 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系 ...

  9. php 23种设计模型 - 代理模式

    代理模式(Proxy) 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 介 ...

随机推荐

  1. KMP 入门

    再次学习 \(\rm KMP\) 后不一样的理解. 一些概念 定义字符串 \(S\) 的真 前/后 缀为非自身的 前/后 缀. 定义字符串 \(S\) 的 \(border\) 为 \(S\) 的公共 ...

  2. springboot加载外部配置文件

    网上搜集和整理如下(自己已验证过) 1. war包在tomcat中加载外部配置文件 war包运行在独立tomcat下时,如何加载war包外部配置application.properties,以达到每次 ...

  3. Plist存储

  4. 简单实现支付密码输入框 By HL

    密码输入框在微信,支付宝中比较常见 主要功能点 1.6位(或者N位)密码输入框封装

  5. 有关 iOS 的开发证书、应用标识、设备标识、配置文件以及密钥 #DF

    iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书, 以下是对iOS开发的常用证书和密钥等的逐一简单说明: 证书 iOS常用的证书包括开发证书和发布证书,无论是真机调试还是最终发布应用到A ...

  6. 「 题解 」P2487 [SDOI2011]拦截导弹

    简单题意 给定 \(n\) 个数对 \((h_i, v_i)\). 求: 最长不上升子序列的长度. 对于每个 \(i\),分别求出包含数对 \((h_i, v_i)\) 的最长上升子序列的个数和最长不 ...

  7. LeetCode随缘刷题之最长回文子串

    这一题我用的相对比较笨的方法. 相对于大佬们用的动态规划法,比较复杂.但却更容易理解,我主要是通过记录下标来确定最长回文串的. package leetcode.day_12_06; /** * 给你 ...

  8. Vue3.X安装

    1.查看node.js和npm版本 $ node -v //建议v10以上版本 $ npm -v 2.若已安装了2.x的旧版本,需要先卸载 npm uninstall vue-cli -g 3.安装淘 ...

  9. Java执行cmd命令、bat脚本、linux命令,shell脚本等

    1.Windows下执行cmd命令 如复制 D:\tmp\my.txt 到D:\tmp\my_by_only_cmd.txt 现文件如图示: 执行代码: private static void run ...

  10. ajax请求egg用nginx转发跨域问题

    火狐浏览器报的 谷歌浏览器报的 前提: npm i egg-cors --save config 文件下的pulgin.js 已经添加 //启用跨域支持 exports.cors = { enable ...