行为模式---之--访问者模式

所谓双分派,就是根据方法的接收者以及某一个参量的类型的不一样而执行不一样的代码。Java语言以方法重载的试支持静态的多分派,而经过方法的重写支持动态的单分派
 
访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操做。一旦这些操做须要修改的话,接受这个操做的数据结构则能够保持不变。
 
    访问者模式适用于数据结构相对未定的系统,它把数据结构和做用于结构之上的操做之间的耦合解脱开,使得操做集合能够相对自由地演化。
 
所涉及角色:
1.抽象访问者(Visitor)角色:声明了一个或多个访问操做,造成全部的具体元素角色必须实现的接口
2.具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操做。
3.抽象节点(Node)角色:声明一个接受操做,接受一个访问者对象做为一个参量
4.具体节点(Node)角色:实现抽象元素所规定的接受操做
5.结构对象(ObjectStructure)角色:有以下责任,能够遍历结构中的全部元素,若是须要,提供一个高层次的接口让访问者对象能够访问每个元素,若是须要,能够设计成一个复合对象或者一个汇集
 
示例代码:
  1 public class Client {
  2     private static ObjectStructure Objects;
  3     private static Visitor visitor;
  4     public static void main(String[] args) {
  5         //建立一个结构对象
  6         Objects = new ObjectStructure();
  7         //给结构增长一个节点
  8         Objects.add(new NodeA());
  9         //给结构增长一个节点
 10         Objects.add(new NodeB());
 11         //建立一个新访问者
 12         visitor = new VisitorA();
 13         //让访问者访问结构
 14         Objects.action(visitor);
 15     }
 16 }
 17 //抽象访问者
 18 interface Visitor{
 19     //对应于nodeA的访问操做
 20     void visit(NodeA node);
 21     //对应于nodeB的访问操做
 22     void visit(NodeB node);
 23     
 24 }
 25 //具体访问者A
 26 class VisitorA implements Visitor{
 27 
 28     @Override
 29     public void visit(NodeA node) {
 30         System.out.println(node.operationA());
 31     }
 32 
 33     @Override
 34     public void visit(NodeB node) {
 35         System.out.println(node.operationB());
 36     }
 37     
 38 }
 39 //具体访问者B
 40 class VisitorB implements Visitor{
 41 
 42     @Override
 43     public void visit(NodeA node) {
 44         System.out.println(node.operationA());
 45     }
 46 
 47     @Override
 48     public void visit(NodeB node) {
 49         System.out.println(node.operationB());
 50     }
 51     
 52 }
 53 //抽象结点
 54 abstract class Node{
 55     //接受操做
 56     public abstract void accept(Visitor visitor);
 57 }
 58 //具体节点A
 59 class NodeA extends Node{
 60 
 61     @Override
 62     public void accept(Visitor visitor) {
 63         visitor.visit(this);
 64     }
 65     //nodeA的特有商业方法
 66     public String operationA(){
 67         return "Node A is visited";
 68     }
 69 }
 70 //具体节点B
 71 class NodeB extends Node{
 72     @Override
 73     public void accept(Visitor visitor) {
 74         visitor.visit(this);
 75     }
 76     //nodeA的特有商业方法
 77     public String operationB(){
 78         return "Node B is visited";
 79     }
 80 }
 81 //结构对象角色,它持有一个汇集,并向外界提供add()方法做为对汇集的管理 操做,经过调用这个方法,能够动态地增长一个新的节点。
 82 class ObjectStructure{
 83     private Vector nodes;
 84     private Node node;
 85     //构造方法
 86     public ObjectStructure(){
 87         nodes = new Vector();
 88     }
 89     //执行访问操做
 90     public void action(Visitor visitor){
 91         for(Iterator it = nodes.iterator();it.hasNext();){
 92             node = (Node)it.next();
 93             node.accept(visitor);
 94         }
 95     }
 96     
 97     //增长一个新的元素
 98     public void add(Node node){
 99         nodes.add(node);
100     }
101 }
102 //此示意性实现中并无出现一个复杂的具备多个树枝节点的对象树结构,可是,在实际系统中访问者模式一般用来处理复杂的对象树结构的,并且
103 //访问者模式能够用来处理跨越多个等级结构的树结构问题。这正是访问者模式的功能强大之处。

 

访问者模式不该当在什么状况下使用?
1.倾斜的可扩展性:访问者模式应当在被访问的类结构很是稳定的状况下使用。换另外一句话,系统不多出现须要加入新节点的状况。若是出现须要加入新节点的状况,那时就必须在每个访问对象里加入一个对应于这个新节点的访问操做,而这是对一个系统的大规模修改,是违反“开闭”原则 的
    访问者模式容许在节点中加入新的方法,相应的仅仅须要在一个新的访问者类中加入此方法,而不须要在每个访问者类中都加入此方法。
访问者模式提供了倾斜的可扩展设计,方法集合的扩展性和类集合的不可扩展性。若是系统的数据结构是频繁变化 的,则不适合使用访问者模式
 
优势
1.访问者模式使得增长新的操做变得容易,若是一个操做依赖于一个复杂的结构对象的话,那么通常而言,增长新的操做会很复杂。而使用访问者模式,增长新的操做就意味着增长一个新的访问者类,很容易
2.访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中
3.访问者模式能够跨过几个类的等级结构访问属于不一样的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不一样等级结构的对象。访问者模式能够作到这一点
4.积累状态。每个单独的访问者对象都集中了相关的行为,从而也就能够在访问地过程当中将执行操做的状态积累在本身内部,而不是分散到不少的节点对象中。这是有益于系统维护的优势
缺点:
1.增长新的节点类变得很困难。每增长一个新的节点都意味着要在抽象访问者角色中增长一个新的抽象操做,并在每个具体访问者类中增长相应的具体操做。
2.破坏封装。访问者模式要求访问者对象访问并调用每个节点对象的操做,这隐含了一个对全部节点对象的要求:它们必须暴露一些本身的操做和内部状态。否则,访问者的访问就变得没有意义。因为访问者对象本身会积累访问操做所须要的状态,从而使这些状态再也不存储在节点对象中,这也是破坏封装的。
相关文章
相关标签/搜索