访问者模式

 

  我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。
我们的访问者模式可以很好付诸在这个场景中:对于银行柜台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。
而我们作为访问者,今天来银行可能是取消费流水,明天来银行可能是去办理手机银行业务,这些是我们访问者的操作,一直是在变化的。   访问者模式主要将数据结构与数据操作分离。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操,即动态的添加访问者角色。   访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。   访问者模式利用了双重分派。先将访问者传入元素对象的Accept方法中,然后元素对象再将自己传入访问者,之后访问者执行元素的相应方法。   访问者模式使得增加新的操作变得很容易。使用访问者模式可以在不用修改具体元素类的情况下增加新的操作。它主要是通过元素类的accept方法来接受一个新的visitor对象来实现的。
如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
  积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点

 

 

  1 <?php
  2 
  3 /**
  4  * 和观察者模式有一丝相似
  5  */
  6 
  7 /**
  8  * 抽象访问者角色, 要定义好针对所有元素的处理操作
  9  */
 10 interface Visitor {
 11     public function visitConcreteElementA(ConcreteElementA $elementA);
 12     public function visitConcreteElementB(concreteElementB $elementB);
 13 }
 14 
 15 /**
 16  * 抽象元素角色
 17  */
 18 interface Element {
 19     public function accept(Visitor $visitor);
 20 }
 21 
 22 
 23 
 24 
 25 
 26 /**
 27  * 具体的访问者1
 28  */
 29 class ConcreteVisitor1 implements Visitor {
 30     private $_name;
 31 
 32     public function __construct($name)
 33     {
 34         $this->_name = $name;
 35     }
 36 
 37     public function visitConcreteElementA(ConcreteElementA $elementA)
 38     {
 39         echo "<br/>", "哈哈, 小妞({$elementA->getName()}), 给本大爷({$this->_name})笑一个";
 40     }
 41 
 42     public function visitConcreteElementB(ConcreteElementB $elementB)
 43     {
 44         echo "<br/>", "哈哈, 小妞({$elementB->getName()}), 给本大爷({$this->_name})笑一个";
 45     }
 46 }
 47 
 48 /**
 49  * 具体的访问者2
 50  */
 51 class ConcreteVisitor2 implements Visitor {
 52     private $_name;
 53 
 54     public function __construct($name)
 55     {
 56         $this->_name = $name;
 57     }
 58 
 59     public function visitConcreteElementA(ConcreteElementA $elementA)
 60     {
 61         echo "<br/>", "哈哈, 小妞({$elementA->getName()}), 给本大爷({$this->_name})笑一个";
 62     }
 63 
 64     public function visitConcreteElementB(ConcreteElementB $elementB)
 65     {
 66         echo "<br/>", "哈哈, 小妞({$elementB->getName()}), 给本大爷({$this->_name})笑一个";
 67     }
 68 }
 69 
 70 
 71 
 72 
 73 
 74 /**
 75  * 具体元素A
 76  */
 77 class ConcreteElementA implements Element {
 78     private $_name;
 79 
 80     public function __construct($name)
 81     {
 82         $this->_name = $name;
 83     }
 84 
 85     public function getName()
 86     {
 87         return $this->_name;
 88     }
 89 
 90     /**
 91      * @param Visitor $visitor  接受访问者调用它针对该元素的新方法
 92      */
 93     public function accept(Visitor $visitor)
 94     {
 95         $visitor->visitConcreteElementA($this);
 96     }
 97 }
 98 
 99 /**
100  * 具体元素B
101  */
102 class ConcreteElementB implements Element {
103     private $_name;
104 
105     public function __construct($name)
106     {
107         $this->_name = $name;
108     }
109 
110     public function getName()
111     {
112         return $this->_name;
113     }
114 
115     /**
116      * @param Visitor $visitor  接受访问者调用它针对该元素的新方法
117      */
118     public function accept(Visitor $visitor)
119     {
120         $visitor->visitConcreteElementB($this);
121     }
122 }
123 
124 
125 
126 
127 /**
128  * 对象结构 即元素的集合
129  */
130 class ObjectStructure {
131     private $_collection;           //具体的元素的集合
132 
133     public function __construct()
134     {
135         $this->_collection = [];
136     }
137 
138     public function attach(Element $element) {
139         return array_push($this->_collection, $element);
140     }
141 
142     public function detach(Element $element) {
143         $index = array_search($element, $this->_collection);
144 
145         if ($index !== FALSE) {
146             unset($this->_collection[$index]);
147         }
148         return $index;
149     }
150 
151     /**
152      * 访问者可以访问这些元素集合
153      *
154      * @param Visitor $visitor
155      */
156     public function accept(Visitor $visitor) {
157         foreach ($this->_collection as $element) {
158             $element->accept($visitor);
159         }
160     }
161 }
162 
163 
164 
165 // client
166 $elementA = new ConcreteElementA("小花");
167 $elementB = new ConcreteElementB("云彩");
168 
169 $visitor1 = new ConcreteVisitor1("路人甲");
170 $visitor2 = new ConcreteVisitor2("流氓乙");
171 
172 $os = new ObjectStructure();
173 $os->attach($elementA);
174 $os->attach($elementB);
175 
176 $os->accept($visitor1);
177 $os->accept($visitor2);
178 
179 
180 
181 /*
182     哈哈, 小妞(小花), 给本大爷(路人甲)笑一个
183     哈哈, 小妞(云彩), 给本大爷(路人甲)笑一个
184     哈哈, 小妞(小花), 给本大爷(流氓乙)笑一个
185     哈哈, 小妞(云彩), 给本大爷(流氓乙)笑一个
186  */
View Code

 

posted @ 2017-01-09 15:44  _logan  阅读(133)  评论(0编辑  收藏  举报