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

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

主要角色

抽象访问者角色(Visitor):为该对象结构(ObjectStructure)中的每一个具体元素提供一个访问操作接口。该操作接口的名字和参数标识了 要访问的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
具体访问者角色(ConcreteVisitor):实现抽象访问者角色接口中针对各个具体元素角色声明的操作。
抽象节点(Node)角色:该接口定义一个accept操作接受具体的访问者。
具体节点(Node)角色:实现抽象节点角色中的accept操作。

对象结构角色(ObjectStructure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合(在PHP中我们使用数组代替,因为PHP中的数组本来就是一个可以放置任何类型数据的集合)
适用性

访问者模式多用在聚集类型多样的情况下。在普通的形式下必须判断每个元素是属于什么类型然后进行相应的操作,从而诞生出冗长的条件转移语句。而访问者模式则可以比较好的解决这个问题。对每个元素统一调用element−>accept(vistor)即可。
访问者模式多用于被访问的类结构比较稳定的情况下,即不会随便添加子类。访问者模式允许被访问结构添加新的方法。

<?php
interface Visitor { // 抽象访问者角色
public function visitConcreteElementA(ConcreteElementA $elementA);
public function visitConcreteElementB(concreteElementB $elementB);
} interface Element { // 抽象节点角色
public function accept(Visitor $visitor);
} class ConcreteVisitor1 implements Visitor { // 具体的访问者1
public function visitConcreteElementA(ConcreteElementA $elementA) {}
public function visitConcreteElementB(ConcreteElementB $elementB) {}
} class ConcreteVisitor2 implements Visitor { // 具体的访问者2
public function visitConcreteElementA(ConcreteElementA $elementA) {}
public function visitConcreteElementB(ConcreteElementB $elementB) {}
} class ConcreteElementA implements Element { // 具体元素A
private $_name;
public function __construct($name) { $this->_name = $name; }
public function getName() { return $this->_name; }
public function accept(Visitor $visitor) { // 接受访问者调用它针对该元素的新方法
$visitor->visitConcreteElementA($this);
}
} class ConcreteElementB implements Element { // 具体元素B
private $_name;
public function __construct($name) { $this->_name = $name;}
public function getName() { return $this->_name; }
public function accept(Visitor $visitor) { // 接受访问者调用它针对该元素的新方法
$visitor->visitConcreteElementB($this);
}
} class ObjectStructure { // 对象结构 即元素的集合
private $_collection;
public function __construct() { $this->_collection = array(); }
public function attach(Element $element) {
return array_push($this->_collection, $element);
}
public function detach(Element $element) {
$index = array_search($element, $this->_collection);
if ($index !== FALSE) {
unset($this->_collection[$index]);
}
return $index;
}
public function accept(Visitor $visitor) {
foreach ($this->_collection as $element) {
$element->accept($visitor);
}
}
} // client
$elementA = new ConcreteElementA("ElementA");
$elementB = new ConcreteElementB("ElementB");
$elementA2 = new ConcreteElementB("ElementA2");
$visitor1 = new ConcreteVisitor1();
$visitor2 = new ConcreteVisitor2(); $os = new ObjectStructure();
$os->attach($elementA);
$os->attach($elementB);
$os->attach($elementA2);
$os->detach($elementA);
$os->accept($visitor1);
$os->accept($visitor2);

最新文章

  1. Windows 8.1 新增控件之 CommandBar
  2. Unity3d NavMesh获得地面高度
  3. paip.java c# .net php python调用c++ c dll so windows api 总结
  4. Sublime 将 Tab 转为空格
  5. jquery easy ui 1.3.4 内容组件(2)
  6. FPGA同步复位异步复位
  7. C# KeyValuePair&lt;TKey,TValue&gt;与Container
  8. 【转】Java基本数据类型
  9. java传值与传引用总结
  10. 一入OI深似海 1 —— 偶然遇见,命运选择
  11. app在admin中显示成我们想要的中文名
  12. [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点
  13. 命令纠正工具 thefuck 的简单使用
  14. Numpy np.array 相关常用操作学习笔记
  15. Access is denied (user is anonymous); redirecting to authentication entry point
  16. Java加密和C#解密=&gt;DES方法
  17. Hive 大数据倾斜总结
  18. C++ readdir、readdir_r函数
  19. SaltStack之编译安装LNMP环境
  20. eclipse中Web Deployment Assembly与build path作用

热门文章

  1. 2017EC Final L SOS——找规律&amp;&amp;博弈
  2. 趋势投资tz-proj springcloud (vue redis)
  3. ES5新增的数组方法
  4. DevExpress.XtraEditors.Repository.RepositoryItem.CreateDesigner()
  5. PSQLException: An I/O error occurred while sending to the backend.
  6. SpringBoot升级报错:Failed to bind properties under &#39;logging.level&#39;
  7. (ACP)敏捷项目管理
  8. Spring Transaction 使用入门
  9. Django纪要
  10. 运行时异常RuntimeException捕获的小测试