天天看点

24访问者模式

一、访问者模式定义

1.访问者模式是一种将数据结构与数据操作分离的设计模式,是指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。属于行为型模式。

2.访问者模式被称为最复杂的设计模式,并且使用频率不高,设计模式的作者也评价为:大多情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就真的需要使用了。访问者模式的基本思想是,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个accept()方法用来接受访问者对象的访问。不同的访问者对同一元素的访问内容不同,使得相同的元素集合可以产生不同的数据结果。accept()方法可以接收不同的访问者对象,然后在内部将自己(元素)转发到接收到的访问者对象的visit()方法内。访问者内部对应类型的visit()方法就会得到回调执行,对元素进行操作。也即是通过两次动态分发(第一次是对访问者的分发accept()方法,第二次是对元素的分发visit()方法),才最终将一个具体的元素传递到一个具体的访问者。如此一来,就解耦了数据结构与操作,且数据操作不会改变元素状态

3.访问者模式的核心是解耦数据结构与数据操作,使得对元素的操作具备优秀的扩展性。可以通过扩展不同的数据操作类型(访问者)实现对相同元素集的不同的操作

4.访问者模式的适用场景:

  A.数据结构稳定,作用于数据结构的操作经常变化的场景

  B.需要数据结构与数据操作分离的场景

  C.需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景

二、访问者模式示例

1.访问者模式一般包含5种角色:

  A.抽象访问者(Visitor):接口或抽象类

  B.具体访问者(ConcreteVisitor):实现对具体元素的操作

  C.抽象元素(Element):接口或抽象类,定义了一个接受访问者访问的方法accept(),表示所有元素类型都支持被访问者访问

  D.具体元素(ConcreteElement):具体元素类型,提供接受访问者的具体实现,通常的实现都为:visitor.visit(this)

  E.结构对象(ObjectStructure):该类内部维护了元素集合,并提供方法接受访问者对该集合所有元素进行操作

2.代码示例

1 // 抽象访问者
 2 public interface IVisitor {
 3 
 4     void visit(ConcreteElementA element);
 5 
 6     void visit(ConcreteElementB element);
 7 }
 8 
 9 // 具体访问者
10 public class ConcreteVisitorA implements IVisitor {
11 
12     public void visit(ConcreteElementA element) {
13         String result = element.operationA();
14         System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
15     }
16 
17     public void visit(ConcreteElementB element) {
18         int result = element.operationB();
19         System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
20     }
21 }
22 
23 // 具体访问者
24 public class ConcreteVisitorB implements IVisitor {
25 
26     public void visit(ConcreteElementA element) {
27         String result = element.operationA();
28         System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
29     }
30 
31 
32     public void visit(ConcreteElementB element) {
33         int result = element.operationB();
34         System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
35     }
36 }
37 
38 // 抽象元素
39 public interface IElement {
40     void accept(IVisitor visitor);
41 }
42 
43 // 具体元素
44 public class ConcreteElementA implements IElement {
45 
46     public void accept(IVisitor visitor) {
47         visitor.visit(this);
48     }
49 
50     public String operationA() {
51         return this.getClass().getSimpleName();
52     }
53 
54 }
55 
56 // 具体元素
57 public class ConcreteElementB implements IElement {
58 
59     public void accept(IVisitor visitor) {
60         visitor.visit(this);
61     }
62 
63     public int operationB() {
64         return new Random().nextInt(100);
65     }
66 }
67 
68 // 结构对象
69 public class ObjectStructure {
70     private List<IElement> list = new ArrayList<IElement>();
71 
72     {
73         this.list.add(new ConcreteElementA());
74         this.list.add(new ConcreteElementB());
75     }
76 
77     public void accept(IVisitor visitor) {
78         for (IElement element : this.list) {
79             element.accept(visitor);
80         }
81     }
82 }
83 
84 public class Test {
85 
86     public static void main(String[] args) {
87         ObjectStructure collection = new ObjectStructure();
88         System.out.println("ConcreteVisitorA handle elements:");
89         IVisitor visitorA = new ConcreteVisitorA();
90         collection.accept(visitorA);
91         System.out.println("------------------------------------");
92         System.out.println("ConcreteVisitorB handle elements:");
93         IVisitor visitorB = new ConcreteVisitorB();
94         collection.accept(visitorB);
95     }
96 
97 }      

3.访问者模式的优缺点

  A.优点

    a.解耦了数据结构和数据操作,使得操作集合可以独立变化

    b.扩展性好:可以通过扩展访问者角色,实现对数据集的不同操作

    c.元素具体类型并非单一,访问者均可操作

    d.各角色职责分离,符合单一职责原则

  B.缺点

继续阅读