关于访问者模式这一篇就够了

访问者模式的概念

访问者模式(Visitor Pattern)是GoF(Gang of Four,即四位作者Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides)提出的23种设计模式中的一种,属于行为模式。它表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

访问者模式涉及以下几个角色:

  1. Visitor(抽象访问者):为该对象结构中具体元素角色声明一个访问操作接口。
  2. ConcreteVisitor(具体访问者):实现Visitor声明的接口。
  3. Element(抽象元素):定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
  4. ConcreteElement(具体元素):实现了Element所定义的接受操作接口。
  5. ObjectStructure(结构对象):能枚举它的元素,并可以提供一个高层接口以允许访问者访问它的元素。

访问者模式的优缺点

优点

  1. 符合单一职责原则:访问者模式中的操作通常与元素类本身关系不大,且是易变的。使用访问者模式可以将这些操作封装在访问者中,使得元素类更加单一且易于维护。
  2. 优秀的扩展性:元素类可以通过接受不同的访问者来实现对不同操作的扩展,无需修改元素类本身。

缺点

  1. 具体元素对访问者公布细节:违反了迪米特原则(Law of Demeter),即一个对象应该对其他对象保持最少的了解。
  2. 具体元素变更比较困难:由于访问者模式依赖于元素类的接口,因此如果元素类的接口发生变化,可能需要修改所有的访问者类。
  3. 违反了依赖倒置原则:访问者模式通常依赖于具体的元素类,而不是抽象接口。

访问者模式的应用场景

  1. 当一个对象结构包含很多类对象,并且需要对这些对象实施一些依赖于其具体类的操作时,可以使用访问者模式。
  2. 当需要在一个对象结构中的对象上进行很多不同的且不相关的操作时,为了避免让这些操作"污染"这些对象的类,可以使用访问者模式。
  3. 当对象结构被多个应用共享时,可以使用访问者模式让每个应用仅包含需要的操作。

代码实现

|---|-------------------------------------------------------|
| | // 抽象访问者接口 |
| | public interface Visitor { |
| | void visit(ConcreteElementA elementA); |
| | void visit(ConcreteElementB elementB); |
| | } |
| | |
| | // 抽象元素接口 |
| | public interface Element { |
| | void accept(Visitor visitor); |
| | } |
| | |
| | // 具体元素A |
| | public class ConcreteElementA implements Element { |
| | @Override |
| | public void accept(Visitor visitor) { |
| | visitor.visit(this); |
| | } |
| | |
| | // 元素A的具体操作 |
| | public void operationA() { |
| | System.out.println("ConcreteElementA operationA"); |
| | } |
| | } |
| | |
| | // 具体元素B |
| | public class ConcreteElementB implements Element { |
| | @Override |
| | public void accept(Visitor visitor) { |
| | visitor.visit(this); |
| | } |
| | |
| | // 元素B的具体操作 |
| | public void operationB() { |
| | System.out.println("ConcreteElementB operationB"); |
| | } |
| | } |
| | |
| | // 具体访问者 |
| | public class ConcreteVisitor implements Visitor { |
| | @Override |
| | public void visit(ConcreteElementA elementA) { |
| | elementA.operationA(); |
| | System.out.println("Visited ConcreteElementA"); |
| | } |
| | |
| | @Override |
| | public void visit(ConcreteElementB elementB) { |
| | elementB.operationB(); |
| | System.out.println("Visited ConcreteElementB"); |
| | } |
| | } |
| | |
| | // 客户端代码 |
| | public class Client { |
| | public static void main(String[] args) { |
| | Element elementA = new ConcreteElementA(); |
| | Element elementB = new ConcreteElementB(); |
| | Visitor visitor = new ConcreteVisitor(); |
| | |
| | // 让元素A接受访问者的访问 |
| | elementA.accept(visitor); |
| | // 让元素B接受访问者的访问 |
| | elementB.accept(visitor); |
| | } |
| | } |

在这个例子中,我们定义了一个Visitor接口和两个实现了Visitor接口的visit方法的ConcreteVisitor类。我们还定义了一个Element接口和两个实现了Element接口的ConcreteElementAConcreteElementB类。每个具体元素类都实现了accept方法,该方法接受一个Visitor对象作为参数,并调用对应的visit方法。

在客户端代码中,我们创建了两个元素对象和一个访问者对象。然后,我们调用每个元素的accept方法,将访问者对象作为参数传递。这样,每个元素就会执行对应的visit方法,完成对元素的访问操作。

这个示例展示了访问者模式的基本结构和用法。在实际应用中,可以根据具体需求对元素和访问者进行扩展和修改。

相关推荐
暴躁哥4 天前
深入理解设计模式之访问者模式
设计模式·访问者模式
琢磨先生David10 天前
Java 访问者模式深度重构:从静态类型到动态行为的响应式设计实践
java·设计模式·访问者模式
搬码临时工19 天前
本地ip如何映射到外网?借助端口映射软件把内网地址给别人用
运维·服务器·网络·tcp/ip·智能路由器·远程工作·访问者模式
敲代码的 蜡笔小新22 天前
【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀
unity·设计模式·c#·访问者模式
Cuit小唐1 个月前
C++ 访问者模式详解
访问者模式
Niuguangshuo1 个月前
Python 设计模式:访问者模式
python·设计模式·访问者模式
Pasregret1 个月前
访问者模式:分离数据结构与操作的设计模式
数据结构·设计模式·访问者模式
YHY_13s1 个月前
访问者模式
c++·访问者模式
全栈老李技术面试2 个月前
【高频考点精讲】JavaScript中的访问者模式:从AST解析到数据转换的艺术
开发语言·前端·javascript·面试·html·访问者模式
nlog3n2 个月前
Java访问者模式详解
java·开发语言·访问者模式