• 访问者模式简介


    概念

    访问者模式(Visitor pattern)是一种行为型设计模式,它允许在不修改已有对象结构的情况下定义新操作。该模式将数据结构与操作分离,使得新增操作变得容易,并且可以在不同的数据结构上复用相同的操作。

    特点

    1. 将操作封装到独立的访问者类中,使得添加新的操作变得简单。
    2. 可以对一个对象结构中的元素进行多种不同类型的遍历和处理。
    3. 访问者模式通过双重分派来实现动态绑定,即运行时根据具体元素类型调用对应访问者方法。

    优点

    1. 增加新的具体访问者或元素类都比较容易扩展,符合开闭原则。
    2. 将相关行为集中到一个类中,提高代码可维护性和可读性。
    3. 具体元素类无需关心如何执行具体操作逻辑,只需要接受访问者并调用自身方法即可。

    缺点

    1. 增加新元素会涉及所有具体访问者类进行修改,在存在大量元素和/或具体访问者时可能导致代码改动较大。
    2. 访问者模式增加了系统复杂度,并且可能降低运行效率。

    适用场景

    1. 需要对一个复杂对象结构中的元素进行不同类型的操作,而又不希望这些操作污染元素类。
    2. 需要在运行时动态添加新的操作,且这些操作可能是不断变化的。
    3. 对象结构稳定,但经常需要定义新的操作。

    实现方式

    通过将访问者对象传递给元素类,在元素类内部根据具体访问者类型调用对应方法。此方式只有一次动态绑定。

    实现原理:

    1. 定义访问者接口(Visitor):该接口声明了多个重载方法,每个方法对应一个具体元素类,并且传入具体元素对象作为参数。
    2. 定义具体访问者类(ConcreteVisitor):实现了访问者接口,在每个visit方法中根据传入的具体元素类型进行相应操作。
    3. 定义抽象元素类(Element):声明accept方法,用于接受访问者对象并调用其visit方法。
    4. 定义具体元素类(ElementAElementB):继承自抽象元素类,实现accept方法,在其中将自身作为参数调用访问者对象的visit方法。

    实现代码:

    1. interface Visitor {
    2. void visit(ElementA element);
    3. void visit(ElementB element);
    4. }
    5. class ConcreteVisitor implements Visitor {
    6. @Override
    7. public void visit(ElementA element) {
    8. // 对ElementA进行操作逻辑
    9. System.out.println("Visiting Element A");
    10. }
    11. @Override
    12. public void visit(ElementB element) {
    13. // 对ElementB进行操作逻辑
    14. System.out.println("Visiting Element B");
    15. }
    16. }
    17. abstract class Element {
    18. public abstract void accept(Visitor visitor);
    19. }
    20. class ElementA extends Element {
    21. @Override
    22. public void accept(Visitor visitor) {
    23. visitor.visit(this);
    24. }
    25. }
    26. class ElementB extends Element {
    27. @Override
    28. public void accept(Visitor visitor) {
    29. visitor.visit(this);
    30. }
    31. }
    32. public class Main {
    33. public static void main(String[] args) {
    34. Element elementA = new ElementA();
    35. Element elementB = new ElementB();
    36. Visitor visitor = new ConcreteVisitor();
    37. elementA.accept(visitor); // 调用ElementA的accept方法,并传入visitor对象
    38. elementB.accept(visitor); // 调用ElementB的accept方法,并传入visitor对象
    39. }
    40. }

    存在问题:
    单分派方式的实现原理相对简单,但它有一个明显的缺点:每次新增具体元素类时,都需要在访问者接口和具体访问者类中添加对应的visit方法。这样会导致具体访问者类和抽象元素类之间的耦合增加,当元素和操作数量庞大时,维护起来可能会比较困难。

    另外,在单分派方式下,动态绑定只发生一次,即在调用accept方法时根据具体元素类型选择合适的visit方法。因此,在运行时无法根据不同操作类型再进行动态绑定。

  • 相关阅读:
    TSINGSEE青犀睡岗离岗检测算法——确保加油站安全运营
    如何使IOT2050成为PN设备
    方法的重写(override / overwrite)
    回溯法求解n个元素的集合的幂集
    大模型都在用的:旋转位置编码
    【面试官让我十分钟实现一个链表?一个双向带头循环链表甩给面试官】
    Java 求两个向量余弦相似度计算代码
    小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c
    抽象方法及接口的使用概念
    Linux常用命令速查手册——嘎嘎管用
  • 原文地址:https://blog.csdn.net/aidscooler/article/details/132845650