访问者模式 访问者模式是一种集中规整模式,适合用于重构项目时(重构时需求已经清晰,原有的功能点也明确)
定义 封装一些用于某种数据结构中的各个元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的新操作。
角色 Visitor 抽象访问者 抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法的参数定义哪些对象是可以被访问的。
1 2 3 4 public  interface  IVisitor     public  void  visit (ConcreteElement1 el1)      public  void  visit (ConcreteElement2 el2)  } 
ConcreteVisitor 具体访问者 影响访问者访问到一个类后该做什么事情。
1 2 3 4 5 6 7 8 public  class  Visitor  implements  IVisitor     public  void  visit (ConcreteElement1 el1)          el1.doSomething();     }     public  void  visit (ConcreteElement2 el2)          el2.doSomething();     } } 
Element 抽象元素 接口或者抽象类,声明接受哪一类访问者访问。
1 2 3 4 5 6 public  abstract  class  Element          public  abstract  void  doSomething ()           public  abstract  void  accept (IVisitor visitor)  } 
ConcreteElement 具体元素 实现accept方法, 通常是 visitor.visit(this)模式。
1 2 3 4 5 6 7 8 9 10 11 12 public  class  ConcreteElement1  extends  Element     public  void  doSomething ()      public  void  accept (IVisitor visitor)          visitor.visit(this );     } } public  class  ConcreteElement2  extends  Element     public  void  doSomething ()      public  void  accept (IVisitor visitor)          visitor.visit(this );     } } 
ObjectStructure结构对象 元素生产者,一般容纳在多个不同类、不同接口的容器,如List/Set/Map。
1 2 3 4 5 public  class  ObjectStructure     public  static  Element createElement ()          return  new  Random().nextInt(10 ) > 5  ? new  ConcreteElement1() : new  ConcreteElement2();     } } 
使用 1 2 3 for (int  i = 0 ; i < 10  ; i++){     ObjectStructure.createElement().accept(new  Visitor()); } 
优点 
缺点 
违背了迪米特法则,Element具体的细节需要公布给Visitor 
具体元素变更比较困难,元素增加/减少字段Visitor都需要修改 
违背了依赖倒置原则,访问者依赖的是具体的元素,而不是抽象元素。 
 
使用场景 当一个对象结构包含很多类对象,它们有不同的接口,需要对这些对象实施一些依赖于其具体类的操作。
双分派 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  abstract  class  AbsActor     public  void  act (Role role)          System.out.println("Actor can act any role." );     }     public  void  act (KungFuRole role)          System.out.println("Actor can act Kungfu Role." );     } } public  class  YongActor  extends  AbsActor     public  void  act (KungFuRole role)          System.out.println("Yong Man Lov Act KungFu Role." );     } } public  class  OldActor  extends  AbsActor     public  void  act (KungFuRole role)          System.out.println("Old Man Can Not Act KungFu Role." )     } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 public  interface  Role     public  void  accept (AbsActor actor)  } public  class  KungFuRole  extends  Role     public  void  accept (AbsActor actor)          actor.act(this );     } } public  class  IdiotRole  extends  Role     public  void  accept (AbsActor actor)          actor.act(this );     } } 
1 2 3 4 AbsActor actor = new  OldActor(); Role role = new  KungFuRole(); actor.act(role);  actor.act(new  KungFuRole());  
1 2 3 4 AbsActor actor = new  OldActor(); Role role = new  KungFuRole(); role.accept(actor);