直观对比一下两种设计模式,左图:访问者模式;右图:策略模式。可发现,访问者模式相当于两个策略模式的“并联”。
访问者模式(Visitor)定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。访问者模式适合处理多对多的关系。
访问者模式的优点有:
1、扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
2、复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
3、灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
4、符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
基础数据结构:
1 //材料集Element-Set 2 public class ObjectStructure { 3 private List<Element> list = new ArrayList<Element>(); 4 5 // 指定一个Visitor,由其访问列表list中的每一个元素 6 public void accept(Visitor visitor) { 7 Iterator<Element> i = list.iterator(); 8 while (i.hasNext()) { 9 Element element = i.next(); 10 element.accept(visitor); 11 } 12 } 13 14 public void add(Element element) { 15 list.add(element); 16 } 17 18 public void remove(Element element) { 19 list.remove(element); 20 } 21 }
被处理元素类(多个):
1 public interface Element { 2 void accept(Visitor visitor); 3 } 4 5 public class ConcreteElementA implements Element { 6 7 public String ID; 8 9 public String Name; 10 11 public void accept(Visitor visitor) 12 { 13 //具体访问者ConcreteVisitorA 14 visitor.visit(this); 15 } 16 public String operationA() 17 { 18 return "具体元素A的操作。"; 19 } 20 } 21 22 public class ConcreteElementB implements Element { 23 24 public int Age; 25 26 public void accept(Visitor visitor) 27 { 28 //具体访问者ConcreteVisitorB 29 visitor.visit(this); 30 } 31 public String operationB() 32 { 33 return "具体元素B的操作。"; 34 } 35 }
访问者类:
1 public interface Visitor { 2 void visit(ConcreteElementA element); 3 void visit(ConcreteElementB element); 4 } 5 6 public class ConcreteVisitorA implements Visitor { 7 public void visit(ConcreteElementA element) 8 { 9 System.out.println("具体访问者A访问-->"+element.operationA()); 10 } 11 public void visit(ConcreteElementB element) 12 { 13 System.out.println("具体访问者A访问-->"+element.operationB()); 14 } 15 } 16 17 public class ConcreteVisitorB implements Visitor { 18 public void visit(ConcreteElementA element) 19 { 20 System.out.println("具体访问者B访问-->"+element.operationA()); 21 } 22 public void visit(ConcreteElementB element) 23 { 24 System.out.println("具体访问者B访问-->"+element.operationB()); 25 } 26 }
调用方式:
1 public class Client { 2 //Visitor是角色 3 //Element是域模型 4 public static void main(String[] args) { 5 // TODO Auto-generated method stub 6 // 声明数据结构 7 ObjectStructure os = new ObjectStructure(); 8 9 //数据结构中添加元素 10 os.add(new ConcreteElementA()); 11 os.add(new ConcreteElementB()); 12 13 //访问者A访问数据结构 14 Visitor visitor = new ConcreteVisitorA(); 15 os.accept(visitor); 16 17 System.out.println("------------------------"); 18 19 //访问者B访问数据结构 20 visitor = new ConcreteVisitorB(); 21 os.accept(visitor); 22 } 23 }
执行结果: