访问者模式

一、什么是访问者模式

Visitor模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作。

二、访问者模式的应用示例

比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。 根据软件设计的开闭原则(对修改关闭,对扩展开放),我们怎么样实现这种需求呢?

三、访问者模式的结构

访问者模式

四、访问者模式的角色和职责

1) 访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。 


2) 具体访问者角色(Concrete Visitor):实现每个由访问者角色(Visitor)声明的操作。 


3) 元素角色(Element):定义一个Accept操作,它以一个访问者为参数。 


4) 具体元素角色(Concrete Element):实现由元素角色提供的Accept操作。


5) 对象结构角色(Object Structure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。 

代码实现:

访问者角色(Visitor)

[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 访问者 
  4.  */  
  5. public interface Visitor {  
  6.     public void visit(Park park);  
  7.     public void visit(ParkA parkA);  
  8.     public void visit(ParkB parkB);  
  9. }  


具体访问者角色(Concrete Visitor):

[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 清洁工A,负责parkA的卫生情况 
  4.  */  
  5. public class VisitorA implements Visitor {  
  6.   
  7.     public void visit(Park park) {  
  8.   
  9.     }  
  10.   
  11.     public void visit(ParkA parkA) {  
  12.         System.out.println("清洁工A:完成公园" + parkA.getName()+ "的卫生");  
  13.     }  
  14.   
  15.     public void visit(ParkB parkB) {  
  16.   
  17.     }  
  18.   
  19. }  
[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 清洁工B,负责公园B部分的卫生 
  4.  */  
  5. public class VisitorB implements Visitor {  
  6.   
  7.     public void visit(Park park) {  
  8.   
  9.     }  
  10.   
  11.     public void visit(ParkA parkA) {  
  12.   
  13.     }  
  14.   
  15.     public void visit(ParkB parkB) {  
  16.         System.out.println("清洁工B:完成公园" + parkB.getName()+"的卫生");  
  17.     }  
  18.   
  19. }  
[java] view plain copy
 
  1. package com.qianyan.ex;  
  2.   
  3. public class VisitorManager implements Visitor {  
  4.   
  5.     public void visit(Park park) {  
  6.         System.out.println("管理员:负责" + park.getName() + "卫生检查");  
  7.     }  
  8.   
  9.     public void visit(ParkA parkA) {  
  10.         System.out.println("管理员:负责公园"+ parkA.getName() +"部分卫生检查");  
  11.     }  
  12.   
  13.     public void visit(ParkB parkB) {  
  14.         System.out.println("管理员:负责公园"+ parkB.getName() +"分部卫生检查");  
  15.     }  
  16.   
  17. }  


元素角色(Element):

[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 公园每一部分的抽象 
  4.  */  
  5. public interface ParkElement {  
  6.     //用来接纳访问者  
  7.     public void accept(Visitor visitor);  
  8. }  


具体元素角色(Concrete Element):

[java] view plain copy
 
  1. package com.qianyan.ex;  
  2.   
  3. public class Park implements ParkElement {  
  4.     private String name;  
  5.     private ParkA parkA;  
  6.     private ParkB parkB;  
  7.       
  8.     public Park() {  
  9.         this.parkA = new ParkA();  
  10.         this.parkB = new ParkB();  
  11.         parkA.setName("A");  
  12.         parkB.setName("B");  
  13.     }  
  14.   
  15.     public void accept(Visitor visitor) {  
  16.         visitor.visit(this);  
  17.         parkA.accept(visitor);  
  18.         parkB.accept(visitor);  
  19.           
  20.     }  
  21.   
  22.     public String getName() {  
  23.         return name;  
  24.     }  
  25.   
  26.     public void setName(String name) {  
  27.         this.name = name;  
  28.     }  
  29.   
  30. }  
[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 公园的A部分 
  4.  */  
  5. public class ParkA implements ParkElement {  
  6.     private String name;  
  7.   
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.   
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.   
  16.     public void accept(Visitor visitor) {  
  17.         visitor.visit(this);  
  18.     }  
  19.   
  20. }  
[java] view plain copy
 
  1. package com.qianyan.ex;  
  2. /* 
  3.  * 公园的B部分 
  4.  */  
  5. public class ParkB implements ParkElement{  
  6.     private String name;  
  7.       
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.   
  12.     public void setName(String name) {  
  13.         this.name = name;  
  14.     }  
  15.   
  16.     public void accept(Visitor visitor) {  
  17.         visitor.visit(this);  
  18.     }  
  19.   
  20. }  


测试类:

[java] view plain copy
 
  1. package com.qianyan.ex;  
  2.   
  3. public class MainClass {  
  4.     public static void main(String[] args) {  
  5.         Park park = new Park();  
  6.         park.setName("锦绣公园");  
  7.         VisitorA visitorA = new VisitorA();  
  8.           
  9.         park.accept(visitorA);  
  10.           
  11.         VisitorB visitorB = new VisitorB();  
  12.         park.accept(visitorB);  
  13.           
  14.         VisitorManager visitorManager = new VisitorManager();  
  15.         park.accept(visitorManager);  
  16.     }  
  17. }  


测试结果:

[java] view plain copy
 
    1. 清洁工A:完成公园A的卫生  
    2. 清洁工B:完成公园B的卫生  
    3. 管理员:负责锦绣公园卫生检查  
    4. 管理员:负责公园A部分卫生检查  
    5. 管理员:负责公园B分部卫生检查