访问者模式
# 访问者模式
# 一、访问者模式
原理:访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。。
优缺点
- 1 优点
- 增加新的操作很容易:可以在不修改元素类的前提下增加新的操作,只需要增加新的访问者类。
- 符合单一职责原则:将操作和数据结构分离,增加了代码的内聚性。
- 符合开闭原则:可以在不修改现有代码的情况下,扩展新的功能。
- 集中相关行为:将相关操作集中到访问者中,使代码更易于理解和维护。
- 灵活性高:可以对不同的对象执行不同的操作,且操作可以根据具体的访问者实现变化。
- 2 缺点
- 元素类的修改较困难:增加新的元素类需要修改所有的访问者类,违背了开闭原则。
- 破坏封装:访问者模式通常需要访问对象的内部状态,因此需要将对象的内部细节暴露出来,破坏了封装性。
- 较高的复杂性:增加了系统的复杂性,特别是在有大量不同类型的元素时。
- 双重分派:实现访问者模式通常需要双重分派,增加了实现的复杂性。
适用场景
- 对象结构相对稳定:对象结构很少变化,但经常需要在此结构上定义新的操作。
- 需要对不同种类的对象执行不同操作:系统中对象种类较多,并且需要对这些对象实施一些依赖于具体类型的操作。
- 对象结构中的类较少变动,而经常需要增加新的操作:如编译器的语法树操作。
# 二、访问者模式基本代码
元素接口
interface Element { void accept(Visitor visitor); }
1
2
3具体元素A,B
class ConcreteElementA implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String operationA() { return "ConcreteElementA's operation."; } } // 具体元素B class ConcreteElementB implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String operationB() { return "ConcreteElementB's operation."; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22访问者接口
interface Visitor { void visit(ConcreteElementA elementA); void visit(ConcreteElementB elementB); }
1
2
3
4具体访问者
class ConcreteVisitor implements Visitor { @Override public void visit(ConcreteElementA elementA) { System.out.println("Visiting " + elementA.operationA()); } @Override public void visit(ConcreteElementB elementB) { System.out.println("Visiting " + elementB.operationB()); } }
1
2
3
4
5
6
7
8
9
10
11客户端
public class VisitorPatternDemo { public static void main(String[] args) { Element elementA = new ConcreteElementA(); Element elementB = new ConcreteElementB(); Visitor visitor = new ConcreteVisitor(); elementA.accept(visitor); elementB.accept(visitor); } }
1
2
3
4
5
6
7
8
9
10
11
# 三、实现方式
在访问者接口中声明一组 “访问” 方法, 分别对应程序中的每个具体元素类。
声明元素接口。 如果程序中已有元素类层次接口, 可在层次结构基类中添加抽象的 “接收” 方法。 该方法必须接受访问者对象作为参数。
在所有具体元素类中实现接收方法。 这些方法必须将调用重定向到当前元素对应的访问者对象中的访问者方法上。
元素类只能通过访问者接口与访问者进行交互。 不过访问者必须知晓所有的具体元素类, 因为这些类在访问者方法中都被作为参数类型引用。
为每个无法在元素层次结构中实现的行为创建一个具体访问者类并实现所有的访问者方法。
你可能会遇到访问者需要访问元素类的部分私有成员变量的情况。 在这种情况下, 你要么将这些变量或方法设为公有, 这将破坏元素的封装; 要么将访问者类嵌入到元素类中。 后一种方式只有在支持嵌套类的编程语言中才可能实现。
客户端必须创建访问者对象并通过 “接收” 方法将其传递给元素。
编辑 (opens new window)