设计模式(十九)—— 访问者模式

访问者模式

定义

封装一些作用于某种数据结构中的各种元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

  • Visitor:抽象访问者,抽象类或者接口,声明访问者可以访问那些元素,具体到程序中就是visit方法的参数定义那些对象是可以被访问的。
  • ConcreteVisitor:具体访问者,影响访问者访问到一个类后要做什么事情。
  • Element:抽象元素,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。
  • ConcreteElement:具体元素,实现accept方法。
  • ObjectStruture:结构对象,元素生产者,一般容纳在多个不同类,不同接口的容器,如List、Set、Map等。

具体实现:

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
public interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}

public class ConcreteVisitorA implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("具体访问者A访问:" + elementA.operationA());
}

@Override
public void visit(ConcreteElementB elementB) {
System.out.println("具体访问者A访问:" + elementB.operationB());
}
}

public class ConcreteVisitorB implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("具体访问者B访问:" + elementA.operationA());
}

@Override
public void visit(ConcreteElementB elementB) {
System.out.println("具体访问者B访问:" + elementB.operationB());
}
}
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
public interface Element {
void accept(Visitor visitor);
}

public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

public String operationA(){
return "具体元素A的操作。";
}
}

public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

public String operationB(){
return "具体元素B的操作。";
}
}
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
public class ObjectStructure {
private List<Element> list = new ArrayList<Element>();

public void accept(Visitor visitor){
Iterator<Element> iterator = list.iterator();
while (iterator.hasNext()){
iterator.next().accept(visitor);
}
}

public void add(Element element){
list.add(element);
}

public void remove(Element element){
list.remove(element);
}
}
public class Main {

public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.add(new ConcreteElementA());
objectStructure.add(new ConcreteElementB());
Visitor visitor = new ConcreteVisitorA();
objectStructure.accept(visitor);
System.out.println("-------------");
Visitor visitor1 = new ConcreteVisitorB();
objectStructure.accept(visitor1);
}
}
// 输出
具体访问者A访问:具体元素A的操作。
具体访问者A访问:具体元素B的操作。
-------------
具体访问者B访问:具体元素A的操作。
具体访问者B访问:具体元素B的操作。

优点

  1. 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  2. 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
  3. 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
  4. 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

缺点

  1. 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
  2. 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
  3. 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。

使用场景

  • 一个对象结构包含很多类对象,他们有不同的接口,想要对这些对象实施一些依赖于其具体类的操作,也就是说用迭代器模式不能胜任的场景。
  • 需要对一个对象结构中的对象进行很多不同并且不相关的操作,想要避免这些操作。
  • 业务规则需要遍历多个不同的对象。

代码:GitHub


欢迎关注公众号:
公众号微信

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
显示 Gitment 评论