大话设计模式-访问者模式

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:16   2462   0

引自原书

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);


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP