【设计模式与体系结构】行为型模式-访问者模式
简介
访问者模式(Visitor Pattern)是一种行为型设计模式,将数据结构与操作(算法)进行分离,使我们在不改变数据结构的前提下定义不同的操作于复杂数据结构的新操作(算法)。
访问者模式的优点
- 符合开闭原则:增加新的访问者类,不需要修改任何源代码,符合开闭原则
- 符合单一职责原则:相关操作都封装在一个访问者,便于维护和复用
访问者模式的缺点
- 若元素类需要发生变化,则不满足开闭原则,且变化成本巨大
- 违背依赖倒置原则:访问者依赖于具体元素,而非抽象
- 破坏封装性:由于访问者模式是双重委派机制,因此会破坏封装性,暴露出部分实现细节
访问者模式的使用场景
当数据结构较为复杂但稳定,且经常需要添加对这个数据结构的不同操作时,适合使用访问者模式。通过将数据结构与操作分离,可以确保对象结构的稳定性,同时允许灵活地添加新功能。
常用命令模板
| 角色 | 推荐命名模板 | 例子 |
|---|---|---|
| 访问者接口 | Visitor | Visitor |
| 具体访问者 | [动词]Visitor 或 [业务]Visitor | SaveVisitor、ReportVisitor |
| 元素接口 | [名词]Element | ShapeElement |
| 具体元素 | [具体类型]Element | CircleElement、RectangleElement |
| 对象结构 | [名词]Structure | ShapeStructure |
正文
动物园中的动物种类一般是比较固定的,不常发生变化。而各种动物的行为等,明显是个性化的。那么就可以以动物园为例讲解访问者模式。
首先定义访问者模式通用的访问者接口 Visitor.java 和元素接口 Element.java:
// 通用访问者接口
public interface Visitor {
void visit(Element element);
}
// 通用元素接口
public interface Element {
void accept(Visitor visitor);
}
比方说某动物园的动物只有老虎和狮子,那么可以定义动物访问者接口 AnimalVisitor.java 和动物元素接口 AnimalElement.java,以及继承自动物元素接口 AnimalElement.java 的狮子类 Lion.java 与老虎类 Tiger.java:
// 动物访问者接口
public interface AnimalVisitor extends Visitor {
void visitTiger(Tiger tiger);
void visitLion(Lion lion);
}
// 动物元素接口
public interface AnimalElement extends Element {
void accept(AnimalVisitor visitor);
}
// 狮子类
public class Lion implements AnimalElement {
@Override
public void accept(AnimalVisitor visitor) {
visitor.visitLion(this);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 老虎类
public class Tiger implements AnimalElement {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public void accept(AnimalVisitor visitor) {
visitor.visitTiger(this);
}
}
各种动物的叫声都是不一致的,不妨定义一个叫声访问者类 Speak.java:
public class Speak implements AnimalVisitor {
@Override
public void visitTiger(Tiger tiger) {
System.out.println(tiger + "虎啸");
}
@Override
public void visitLion(Lion lion) {
System.out.println(lion + "狮吼");
}
@Override
public void visit(Element element) {
System.out.println(element + "叫");
}
}
对于客户端可以使用以下代码:
Speak speak = new Speak();
Lion lion = new Lion();
Tiger tiger = new Tiger();
lion.accept(speak);
tiger.accept(speak);
运行效果如下:

浙公网安备 33010602011771号