引自原书
1.访问者模式适用于数据结构相对稳定的系统
2.它把数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化
3.访问者模式的目的是要把处理从数据结构分离出来
4.有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。
5.访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
6.访问者的缺点就是使得增加新的数据结构变得困难了
大多数时候你并不需要访问者模式。我们很难找到数据结构不变化的情况
abstract class Action {
//得到男人结论或反应
public abstract function getManConclusion(Man $concreteElementA);
//得到女人结论或反应
public abstract function getWomanConclusion(Woman $concreteElementB);
}
abstract class Person {
//接受(它是用来获得‘状态’对象的)
public abstract function accept(Action $visitor);
}
//成功
class Success extends Action {
public function getManConclusion(Man $concreteElementA) {
echo get_class($concreteElementA).' '.get_class($this).'时,背后大多有一个伟大的女人。<br/>';
}
public function getWomanConclusion(Woman $concreteElementB) {
echo get_class($concreteElementB).' '.get_class($this).'时,背后大多有一个不成功的男人。<br/>';
}
}
//失败
class Failing extends Action {
public function getManConclusion(Man $concreteElementA) {
echo get_class($concreteElementA).' '.get_class($this).'时,闷头喝酒,谁也不用劝。<br/>';
}
public function getWomanConclusion(Woman $concreteElementB) {
echo get_class($concreteElementB).' '.get_class($this).'时,眼泪汪汪,谁也劝不了。<br/>';
}
}
//恋爱
class Amativeness extends Action {
public function getManConclusion(Man $concreteElementA) {
echo get_class($concreteElementA).' '.get_class($this).'时,凡事不懂也要装懂。<br/>';
}
public function getWomanConclusion(Woman $concreteElementB) {
echo get_class($concreteElementB).' '.get_class($this).'时,遇事也装作不懂。<br/>';
}
}
//结婚
class Marriage extends Action {
public function getManConclusion(Man $concreteElementA) {
echo get_class($concreteElementA).' '.get_class($this).'时,感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。<br/>';
}
public function getWomanConclusion(Woman $concreteElementB) {
echo get_class($concreteElementB).' '.get_class($this).'时,欣慰曰:爱情长跑路漫漫,婚姻保险保平安。<br/>';
}
}
//男人
class Man extends Person {
public function accept(Action $visitor) {
//首先在客户程序中将具体状态作为参数传递给‘男人’类完成了一次分派,然后‘男人’类调用作为参数的‘具体状态’中的方法‘男人反应’,同时将自己(this)作为参数传递进去。这便完成了第二次分派
$visitor->getManConclusion($this);
}
}
//女人
class Woman extends Person {
public function accept(Action $visitor) {
$visitor->getWomanConclusion($this);
}
}
//对象结构
class ObjectStructure {
private $elements;
//增加
public function attach(Person $element) {
$this->elements[] = $element;
}
//移动
public function detach(Person $element) {
unset($this->elements[array_search($element, $this->elements)]);
}
//查看显示(遍历方法)
public function display(Action $visitor) {
foreach($this->elements as $e) {
$e->accept($visitor);
}
}
}
$o = new ObjectStructure();
//在对象结构中加入要对比的‘男人’和‘女人’
$o->attach(new Man());
$o->attach(new Woman());
//成功时的反应
$v1 = new Success();
//查看在各种状态下,‘男人’和‘女人’的反应
$o->display($v1);
//失败时的反应
$v2 = new Failing();
$o->display($v2);
//恋爱时的反应
$v3 = new Amativeness();
$o->display($v3);
//结婚时的反应
$v4 = new Marriage();
$o->display($v4);
访问者模式
//为对象结构中ConcreteElement的每一个类声明一个Visit操作
abstract class Visitor {
public abstract function visitConcreteElementA(ConcreteElementA $concreteElementA);
public abstract function visitConcreteElementB(ConcreteElementB $concreteElementB);
}
//ConcreteVisitor1和ConcreteVisitor2类,具体访问者,实现每个由visitor声明的操作。每个操作实现算法的一部分,而该算法片断乃是对应于结构中对象的类。
class ConcreteVisitor1 extends Visitor {
public function visitConcreteElementA(ConcreteElementA $concreteElementA) {
echo get_class($concreteElementA).'被'.get_class($this).'访问1<br/>';
}
public function visitConcreteElementB(ConcreteElementB $concreteElementB) {
echo get_class($concreteElementB).'被'.get_class($this).'访问1<br/>';
}
}
class ConcreteVisitor2 extends Visitor {
public function visitConcreteElementA(ConcreteElementA $concreteElementA) {
echo get_class($concreteElementA).'被'.get_class($this).'访问2<br/>';
}
public function visitConcreteElementB(ConcreteElementB $concreteElementB) {
echo get_class($concreteElementB).'被'.get_class($this).'访问2<br/>';
}
}
//定义一个accept操作,它以一个访问者为参数。
abstract class Element {
public abstract function Accept(Visitor $visitor);
}
//ConcreteElementA和ConcreteElementB类,具体元素,实现accept操作
class ConcreteElementA extends Element {
//充分利用双分派技术,实现处理与数据结构的分离
public function accept(Visitor $visitor) {
$visitor->visitConcreteElementA($this);
}
//其他相关方法
public function operationA(){
}
}
class ConcreteElementB extends Element {
//充分利用双分派技术,实现处理与数据结构的分离
public function accept(Visitor $visitor) {
$visitor->visitConcreteElementB($this);
}
//其他相关方法
public function operationB(){
}
}
//能枚举它的元素,可以提供一个高层的接口允许访问者访问它的元素。
class ObjectStructure {
private $elements;
public function attach(Element $element) {
$this->elements[] = $element;
}
public function detach(Element $element) {
$this->elements[] = $element;
}
public function accept(Visitor $visitor) {
foreach($this->elements as $e) {
$e->accept($visitor);
}
}
}
$o = new ObjectStructure();
$o->attach(new ConcreteElementA());
$o->attach(new ConcreteElementB());
$v1 = new ConcreteVisitor1();
$v2 = new ConcreteVisitor2();
$o->accept($v1);
$o->accept($v2);