网站首页 > 博客文章 正文
访问者模式(Visitor Pattern)
定义
访问者模式是一种行为型设计模式,它将操作的逻辑从数据结构中分离出来,允许你在不改变数据结构的前提下定义新的操作。通过这种方式,数据结构的变化不会影响操作逻辑,操作逻辑的变化也不会影响数据结构。
核心思想
访问者模式的核心思想是将对象结构和要对这些对象进行的操作分离开来。通过定义一个访问者接口来访问对象结构中的各个元素,具体的操作在访问者类中实现,而对象结构本身不需要进行改变。
组成部分
- Visitor(访问者接口):为对象结构中的每一个元素定义一个访问操作。
- ConcreteVisitor(具体访问者):实现访问者接口,定义对每个元素的具体操作。
- Element(元素接口):定义一个 accept() 方法,接收访问者对象。
- ConcreteElement(具体元素):实现元素接口,在 accept() 方法中调用访问者的相应方法。
- ObjectStructure(对象结构):一个包含元素的集合,提供遍历这些元素的接口。
类图示例
+---------------------+
| Visitor |
+---------------------+
| + visitConcreteA() |
| + visitConcreteB() |
+---------------------+
^
|
+----------------------+
| ConcreteVisitor |
+----------------------+
| + visitConcreteA() |
| + visitConcreteB() |
+----------------------+
+---------------------+
| Element |
+---------------------+
| + accept(Visitor) |
+---------------------+
^
|
+----------------------+
| ConcreteElementA |
+----------------------+
| + accept(Visitor) |
+----------------------+
+----------------------+
| ObjectStructure |
+----------------------+
| + elements |
| + attach(Element) |
| + detach(Element) |
| + accept(Visitor) |
+----------------------+
类图解释
- Visitor(访问者接口):定义了针对每个元素类的访问操作。
- ConcreteVisitor(具体访问者):实现了访问者接口中的方法,包含针对不同元素的具体逻辑。
- Element(元素接口):定义了一个接受访问者的 accept() 方法。
- ConcreteElementA、ConcreteElementB(具体元素):具体实现了 accept() 方法,调用访问者的相应访问方法。
- ObjectStructure(对象结构):持有不同元素的集合,并通过 accept() 方法遍历这些元素,接受访问者的访问。
代码示例
以下是一个访问者模式的示例,展示了如何分离操作和数据结构:
// 访问者接口
interface Visitor {
void visitConcreteElementA(ConcreteElementA elementA);
void visitConcreteElementB(ConcreteElementB elementB);
}
// 具体访问者类
class ConcreteVisitor implements Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA elementA) {
System.out.println("Processing ConcreteElementA");
}
@Override
public void visitConcreteElementB(ConcreteElementB elementB) {
System.out.println("Processing ConcreteElementB");
}
}
// 元素接口
interface Element {
void accept(Visitor visitor);
}
// 具体元素A
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
// 具体元素B
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
// 对象结构类
class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void attach(Element element) {
elements.add(element);
}
public void detach(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
// 客户端代码
public class VisitorPatternExample {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
Element elementA = new ConcreteElementA();
Element elementB = new ConcreteElementB();
objectStructure.attach(elementA);
objectStructure.attach(elementB);
Visitor visitor = new ConcreteVisitor();
objectStructure.accept(visitor); // 访问者处理元素A和B
}
}
代码解释
- Visitor(访问者接口):定义了访问 ConcreteElementA 和 ConcreteElementB 的方法。
- ConcreteVisitor(具体访问者):实现了访问者接口,包含针对不同元素的操作逻辑。
- Element(元素接口):定义了一个接受访问者的方法 accept(),并将访问操作交给访问者处理。
- ConcreteElementA、ConcreteElementB(具体元素):在 accept() 方法中调用了访问者的相应访问方法。
- ObjectStructure(对象结构):持有多个元素,并提供 accept() 方法遍历所有元素并调用访问者。
优点
- 扩展性好:访问者模式可以轻松地增加新的操作,而不需要修改数据结构的代码。
- 符合单一职责原则:操作的逻辑和数据结构的定义被分离开来,各自关注不同的职责。
- 符合开闭原则:通过增加新的访问者类,可以实现对数据结构的新操作,而不影响已有的数据结构代码。
缺点
- 违反依赖倒置原则:具体元素类依赖于访问者接口,如果元素类频繁变更,访问者模式可能会导致类的变更复杂化。
- 不适合频繁变化的数据结构:如果数据结构经常变化,使用访问者模式将导致访问者接口频繁修改,从而降低代码的稳定性。
适用场景
- 数据结构稳定:数据结构相对稳定,但操作逻辑经常需要变更的情况下。
- 需要对对象结构中的元素进行复杂操作:多个不同的操作需要在一组对象上执行时,可以通过访问者模式避免将操作逻辑分散到多个类中。
- 跨多个类的操作:当一项操作需要对多个不相关的类进行处理时,访问者模式可以集中处理这些操作。
总结
访问者模式通过将操作逻辑与数据结构分离,允许在不修改数据结构的情况下扩展新的操作。它特别适用于数据结构相对稳定、操作逻辑频繁变化的场景。访问者模式增强了系统的扩展性,同时保持了代码的清晰性和一致性。
猜你喜欢
- 2024-10-01 设计模式——备忘录模式(备忘录界面设计)
- 2024-10-01 设计模式 之 行为型模式(行为型设计模式特点)
- 2024-10-01 Go语言设计模式-访问者(go语言有设计模式吗)
- 2024-10-01 Spring Boot 实战:运用访问者模式灵活扩展订单处理逻辑
- 2024-10-01 visitor pattern 访问者模式(访问者模式工作原理)
- 2024-10-01 Aha!设计模式(105)-访问者模式(1)
- 2024-10-01 GOF设计模式(命令模式,访问者模式,迭代器模式,观察者模式)
- 2024-10-01 设计模式第2招第9式之解释器模式(解释器原理)
- 2024-10-01 设计模式第2招第1式之观察者模式(观察者设计模式的优点)
- 2024-10-01 「编程设计」访问者(Visitor)模式-补丁式为原体系增加新功能
你 发表评论:
欢迎- 07-07Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- 07-07Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- 07-07Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- 07-07Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- 07-07IT运维必会的30个工具(it运维工具软件)
- 07-07开源项目有你需要的吗?(开源项目什么意思)
- 07-07自动化测试早就跑起来了,为什么测试管理还像在走路?
- 07-07Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- 最近发表
-
- Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- IT运维必会的30个工具(it运维工具软件)
- 开源项目有你需要的吗?(开源项目什么意思)
- 自动化测试早就跑起来了,为什么测试管理还像在走路?
- Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- Cursor 太贵?这套「Cline+OpenRouter+Deepseek+Trae」组合拳更香
- 为什么没人真的用好RAG,坑都在哪里? 谈谈RAG技术架构的演进方向
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)