访问者模式简介 访问者模式是一种行为模式。
访问者模式是一种将数据操作和数据结构分离的设计模式。(觉得太抽象,可以看下面的例子)。
使用场景 
对象结构比较稳定,但经常需要在此对象结构上定义新的操作。 
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。 
 
优缺点 优点 
各角色职责分离,符合单一职责原则 
具有优秀的扩展性 
使得数据结构和作用于结构上的操作解耦,使得操作集合可以独立变化 
灵活性 
 
缺点 
具体元素对访问者公布细节,违反了迪米特原则 
具体元素变更时导致修改成本大 
违反了依赖倒置原则,为了达到“区别对待”而依赖了具体类,没有以来抽象 
 
通用模板 UML 图 
角色介绍 
Visitor :接口或者抽象类,定义了对每个 Element 访问的行为,它的参数就是被访问的元素,它的方法个数理论上与元素的个数是一样的,因此,访问者模式要求元素的类型要稳定,如果经常添加、移除元素类,必然会导致频繁地修改 Visitor 接口,如果出现这种情况,则说明不适合使用访问者模式。ConcreteVisitor :具体的访问者,它需要给出对每一个元素类访问时所产生的具体行为。ElementA、ElementB :具体的元素类,它提供接受访问的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。ObjectStructure :定义当中所提到的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素提供访问者访问。client : 具体的运行代码类 
通用代码 Element接口
1 2 3 4 5 6 7 8 public  interface  Element  {    public  void  accept (Visitor visitor) ; } 
Element Concrete 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  class  ElementA  implements  Element  {    @Override      public  void  accept (Visitor visitor)  {         visitor.visit(this );     }     public  void  operation1 () {         System.out.println("ElementA do operation1" );     } } public  class  ElementB  implements  Element  {    @Override      public  void  accept (Visitor visitor)  {         visitor.visit(this );     }     public  void  operation2 () {         System.out.println("ElementB do operation2" );     } } 
visitor接口
1 2 3 4 5 6 7 8 9 10 public  interface  Visitor  {    public  void  visit (ElementA element1) ;     public  void  visit (ElementB element2) ; } 
visitor concrete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public  class  VisitorA  implements  Visitor  {    @Override      public  void  visit (ElementA elementA)  {         System.out.println("Visitor A start visit ElementA" );         elementA.operation1();     }     @Override      public  void  visit (ElementB elementB)  {         System.out.println("Visitor A start visit ElementB" );         elementB.operation2();     } } public  class  VisitorB  implements  Visitor  {    @Override      public  void  visit (ElementA elementA)  {         System.out.println("Visitor B start visit ElementA" );         elementA.operation1();     }     @Override      public  void  visit (ElementB elementB)  {         System.out.println("Visitor B start visit ElementB" );         elementB.operation2();     } } 
ObjectStructure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public  class  ObjectStructure  {    private  List<Element> elementList;     public  ObjectStructure () {         elementList=new  ArrayList <Element>();         elementList.add(new  ElementA ());         elementList.add(new  ElementB ());     }     public  void  accept (Visitor visitor) {         for (Element element:elementList){             element.accept(visitor);         }     }     public  void  addElement (Element element) {         elementList.add(element);     }     public  void  removeElement (Element element) {         elementList.remove(element);     } } 
最后client调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  class  Client  {    private  Visitor visitor;     private  ObjectStructure objectStructure;     public  void  doVisit () {         ObjectStructure objectStructure=new  ObjectStructure ();         objectStructure.accept(new  VisitorA ());         objectStructure.accept(new  VisitorB ());     }     public  static  void  main (String[] args) {         Client client=new  Client ();         client.doVisit();     } } 
执行结果
1 2 3 4 5 6 7 8 Visitor A start visit ElementA ElementA do operation1 Visitor A start visit ElementB ElementB do operation2 Visitor B start visit ElementA ElementA do operation1 Visitor B start visit ElementB ElementB do operation2 
依然很抽象,看下面的例子吧。
旅游城市例子 访问者模式,用游客访问城市经典的例子再合适不过了.
不同的游客有不同的访问行为,跟团游和自驾游或休闲游在游览景点是的行为也是完全不相同的,完美符合访问者模式中的访问者这一对象。
UML 图 
角色介绍 
City HangzhouCity,HuangshanCity,BeijingCity Tourists WithTheGroupTourists,SelfDriverTourists TravelPlan TravelClient  
实例代码 City
1 2 3 4 5 6 7 8 public  interface  City  {    public  void  accept (Tourists visitor) ; } 
CityConcrete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public  class  BeijingCity  implements  City  {    @Override      public  void  accept (Tourists tourists)  {         tourists.visitBeijing(this );     }          public  String greatWall () {         return  "长城" ;     }          public  String forbiddenCity () {         return  "故宫" ;     }          public  String houhaiBar () {         return  "后海酒吧" ;     } } public  class  HangzhouCity  implements  City  {    @Override      public  void  accept (Tourists tourists)  {         tourists.visitHangzhou(this );     }          public  String westLake () {         return  "西湖" ;     }          public  String zhejiangUniversity () {         return  "浙江大学" ;     }          public  String leifengPagoda () {         return  "雷峰塔" ;     } } public  class  HuangshanCity  implements  City  {    @Override      public  void  accept (Tourists tourists)  {         tourists.visitHuangshan(this );     }          public  String huangshan () {         return  "黄山" ;     } } 
Tourists
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public  interface  Tourists  {         public  void  visitBeijing (BeijingCity beijingCity) ;          public  void  visitHangzhou (HangzhouCity hangzhouCity) ;          public  void  visitHuangshan (HuangshanCity huangshanCity) ; } 
TouristsConcrete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 public  class  SelfDriveTourists  implements  Tourists  {    @Override      public  void  visitBeijing (BeijingCity beijingCity)  {         System.out.println(">>>>>开始自驾旅游北京" );         System.out.println("第1站:" +beijingCity.greatWall());         System.out.println("第2站:" +beijingCity.forbiddenCity());         System.out.println("第3站:" +beijingCity.houhaiBar());         System.out.println(">>>>>结束自驾旅游北京" );     }     @Override      public  void  visitHangzhou (HangzhouCity hangzhouCity)  {         System.out.println(">>>>>开始自驾旅游杭州" );         System.out.println("第1站:" +hangzhouCity.westLake());         System.out.println("第2站:" +hangzhouCity.leifengPagoda());         System.out.println("第3站:" +hangzhouCity.zhejiangUniversity());         System.out.println(">>>>>结束自驾旅游杭州" );     }     @Override      public  void  visitHuangshan (HuangshanCity huangshanCity)  {         System.out.println(">>>>>开始自驾旅游黄山" );         System.out.println("第1站:" +huangshanCity.huangshan());         System.out.println(">>>>>结束自驾旅游黄山" );     } } public  class  WithTheGroupTourists  implements  Tourists  {    @Override      public  void  visitBeijing (BeijingCity beijingCity)  {         System.out.println(">>>>>开始跟团旅游北京" );         System.out.println("第1站:" +beijingCity.houhaiBar());         System.out.println("第2站:" +beijingCity.forbiddenCity());         System.out.println("跟团游时间太紧,无法旅游:" +beijingCity.greatWall());         System.out.println(">>>>>结束跟团旅游北京" );     }     @Override      public  void  visitHangzhou (HangzhouCity hangzhouCity)  {         System.out.println(">>>>>开始跟团旅游杭州" );         System.out.println("第1站:" +hangzhouCity.westLake());         System.out.println("第2站:" +hangzhouCity.zhejiangUniversity());         System.out.println("跟团游时间太紧,无法旅游:" +hangzhouCity.leifengPagoda());         System.out.println(">>>>>结束跟团旅游杭州" );     }     @Override      public  void  visitHuangshan (HuangshanCity huangshanCity)  {         System.out.println(">>>>>开始跟团旅游黄山" );         System.out.println("第1站:" +huangshanCity.huangshan());         System.out.println(">>>>>结束跟团旅游黄山" );     } } 
TravelPlan
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public  class  TravelPlan  {    private  List<City> cityList;     public  TravelPlan () {         cityList=new  ArrayList <City>();         cityList.add(new  BeijingCity ());         cityList.add(new  HangzhouCity ());         cityList.add(new  HuangshanCity ());     }     public  void  travel (Tourists visitor) {         for (City city:cityList){             city.accept(visitor);         }     }     public  void  addCity (City city) {         cityList.add(city);     }     public  void  removeCity (City city) {         cityList.remove(city);     } } 
TravelClient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public  class  TravelClient  {    private  Tourists visitor;     private  TravelPlan travelPlan;     public  void  doTravel () {         TravelPlan travelPlan=new  TravelPlan ();                  travelPlan.travel(new  WithTheGroupTourists ());         System.out.println();         System.out.println();                  travelPlan.travel(new  SelfDriveTourists ());     }     public  static  void  main (String[] args) {         TravelClient travelClient=new  TravelClient ();         travelClient.doTravel();     } } 
执行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 > >>>>开始跟团旅游北京 第1站:后海酒吧 第2站:故宫 跟团游时间太紧,无法旅游:长城 > >>>>结束跟团旅游北京 > >>>>开始跟团旅游杭州 第1站:西湖 第2站:浙江大学 跟团游时间太紧,无法旅游:雷峰塔 > >>>>结束跟团旅游杭州 > >>>>开始跟团旅游黄山 第1站:黄山 > >>>>结束跟团旅游黄山 > >>>>开始自驾旅游北京 第1站:长城 第2站:故宫 第3站:后海酒吧 > >>>>结束自驾旅游北京 > >>>>开始自驾旅游杭州 第1站:西湖 第2站:雷峰塔 第3站:浙江大学 > >>>>结束自驾旅游杭州 > >>>>开始自驾旅游黄山 第1站:黄山 > >>>>结束自驾旅游黄山 
代码 以上例子代码可在个人github项目design-patterns 中找到。
参考文章 访问者模式一篇就够了