访问者模式

访问者(Visitor)模式属于行为型模式的一种。

访问者模式主要用于分离算法和对象结构 ,从而在不修改原有对象的情况下扩展新的操作。它适用于数据结构相对稳定,而操作(行为)容易变化的场景。

访问者模式允许在不修改现有类的情况下,为类层次结构中的对象定义新的操作

访问者模式通过将操作封装到一个独立的类(即访问者)中,使得对象结构与操作解耦。

访问者模式使用了一种名为双分派(在运行时根据两个对象的类型动态选择方法)的技巧。

Java标准库中的 FileVisitor,就是使用的访问者模式。访问者模式的设计比较复杂。

访问者模式适用于以下场景:

  • 数据结构相对稳定,但操作易变的系统(例如编译器、代码分析器)。
  • 需要对对象结构进行不同操作,并且这些操作相对独立,例如报表生成、统计、数据转换。

访问者模式通常有以下组成部分:

  • Visitor(访问者):定义一个访问接口,为不同类型的元素提供不同的访问方法。
  • ConcreteVisitor(具体访问者):访问者的具体实现,具体执行操作。
  • Element(元素接口):定义一个 accept(Visitor v) 方法,允许 Visitor 访问自身。
  • ConcreteElement(具体元素):具体的对象结构,实现 Element 接口,并在 accept(Visitor v) 方法中进行调用。
  • ObjectStructure(对象结构,通常是元素的集合):维护一组 Element 对象,并提供 accept(Visitor v) 方法,让访问者访问所有的元素。

我们模拟一下访问者模式的实现。

1、定义访问者接口

java 复制代码
// 访问者接口
interface Visitor {
    void visit(ConcreteElementA elementA);
    void visit(ConcreteElementB elementB);
}

2、定义具体访问者

java 复制代码
// 具体访问者1
class ConcreteVisitor1 implements Visitor {
    @Override
    public void visit(ConcreteElementA elementA) {
        System.out.println("Visitor1 访问 " + elementA.getName());
    }

    @Override
    public void visit(ConcreteElementB elementB) {
        System.out.println("Visitor1 访问 " + elementB.getName());
    }
}

// 具体访问者2
class ConcreteVisitor2 implements Visitor {
    @Override
    public void visit(ConcreteElementA elementA) {
        System.out.println("Visitor2 访问 " + elementA.getName());
    }

    @Override
    public void visit(ConcreteElementB elementB) {
        System.out.println("Visitor2 访问 " + elementB.getName());
    }
}

3、定义元素接口

java 复制代码
// 元素接口
interface Element {
    void accept(Visitor visitor);
}

4、定义具体元素

java 复制代码
// 具体元素 A
class ConcreteElementA implements Element {
    private String name = "ElementA";

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String getName() {
        return name;
    }
}

// 具体元素 B
class ConcreteElementB implements Element {
    private String name = "ElementB";

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String getName() {
        return name;
    }
}

5、定义对象结构

java 复制代码
// 对象结构,包含多个元素
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
        elements.add(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

6、测试访问者模式

java 复制代码
public class VisitorPatternDemo {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();

        // 添加元素
        structure.addElement(new ConcreteElementA());
        structure.addElement(new ConcreteElementB());

        // 使用不同的访问者访问元素
        Visitor visitor1 = new ConcreteVisitor1();
        Visitor visitor2 = new ConcreteVisitor2();

        System.out.println("使用 Visitor1 访问:");
        structure.accept(visitor1);

        System.out.println("\n使用 Visitor2 访问:");
        structure.accept(visitor2);
    }
}

访问者模式的优缺点

优点:

  • 遵循开闭原则(OCP):可以在不修改元素类的情况下,为其添加新的操作。
  • 将数据结构与行为分离:对象结构负责管理元素,而行为由访问者独立实现,增强了灵活性。
  • 适用于复杂对象结构:当对象结构中包含不同类型的元素时,访问者模式可以统一管理操作逻辑。

缺点:

  • 代码复杂度增加:对于简单对象结构,使用访问者模式可能会增加不必要的复杂性。
  • 每次在元素层次结构中添加或移除一个类时,都要更新所有的访问者。

我们可以将访问者模式视为命令 模式的加强版本,其对象可对不同类的多种对象执行操作。

至此23种设计模式暂告一个段落了。我们将开启下个篇章。

只有读不完的书,哪有不会走的人。-- 烟沙九洲

相关推荐
Boilermaker19926 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维6 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
alonewolf_997 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子7 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34167 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
恋爱绝缘体17 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
wszy18098 小时前
新文章标签:让用户一眼发现最新内容
java·python·harmonyos
wszy18098 小时前
顶部标题栏的设计与实现:让用户知道自己在哪
java·python·react native·harmonyos
程序员小假9 小时前
我们来说一下无锁队列 Disruptor 的原理
java·后端
资生算法程序员_畅想家_剑魔9 小时前
Kotlin常见技术分享-02-相对于Java 的核心优势-协程
java·开发语言·kotlin