(二 十 一)趣学设计模式 之 访问者模式!

目录

    • [一、 啥是访问者模式?](#一、 啥是访问者模式?)
    • [二、 为什么要用访问者模式?](#二、 为什么要用访问者模式?)
    • [三、 访问者模式的实现方式](#三、 访问者模式的实现方式)
    • [四、 访问者模式的优缺点](#四、 访问者模式的优缺点)
    • [五、 访问者模式的应用场景](#五、 访问者模式的应用场景)
    • [六、 总结](#六、 总结)

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解迭代器模式请看: (二 十)趣学设计模式 之 迭代器模式!
✨更多请看个人主页: 码熔burning

这篇文章带你详细认识一下设计模式中的访问者模式

一、 啥是访问者模式?

想象一下,你每年都要去医院做一次体检 🏥。 体检的项目有很多,比如量血压、验血、做心电图等等 🩺。 不同的医生负责不同的检查项目,比如内科医生负责量血压,化验师负责验血 🧪。

访问者模式,就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作! 简单来说,就是把对对象的操作从对象本身分离出来,放到访问者中去执行 👨‍⚕️。

简单来说,就是让不同的"医生(访问者)"来"检查(访问)"你的"身体(元素)",并执行不同的检查项目! 👨‍⚕️+🏥

  • 你想对一个对象结构中的对象执行不同的操作,但是你不想修改这些对象的类: 就像你想让不同的医生检查你的身体,但是你不想修改你的身体结构 🧍!
  • 你想在运行时动态地添加新的操作: 就像你想临时增加一个检查项目,比如做核磁共振 🧲!
  • 你想把操作和对象结构分离,降低耦合度: 就像你想把检查项目和身体分离,让它们可以独立变化 🏥!

二、 为什么要用访问者模式?

用访问者模式,好处多多 👍:

  • 分离操作: 将操作和对象结构分离,降低耦合度 🔗!
  • 增加新操作: 可以在不修改对象结构的前提下,增加新的操作 ➕!
  • 符合单一职责原则: 每个访问者只负责一种操作 👨‍⚕️!
  • 易于扩展: 可以很容易地添加新的访问者和新的元素 🆕!

三、 访问者模式的实现方式

访问者模式主要包含以下几个角色:

  • 访问者(Visitor): 声明一个访问操作,针对对象结构中的每一种元素都提供一个访问方法 👨‍⚕️。
  • 具体访问者(ConcreteVisitor): 实现访问者声明的访问操作,执行具体的操作 👨‍⚕️。
  • 元素(Element): 定义一个接受访问操作的方法(accept),该方法接受一个访问者作为参数 🧍。
  • 具体元素(ConcreteElement): 实现元素定义的接受访问操作的方法,通常是将访问者传递给自身 🧍。
  • 对象结构(ObjectStructure): 包含一组元素,并提供一个方法来让访问者访问这些元素 🏥。

代码示例:

java 复制代码
// 访问者接口:医生
public interface Doctor {
    void visit(BodyPartA bodyPartA); // 检查身体部位 A
    void visit(BodyPartB bodyPartB); // 检查身体部位 B
}

// 具体访问者:内科医生
public class InternalMedicineDoctor implements Doctor {
    @Override
    public void visit(BodyPartA bodyPartA) {
        System.out.println("内科医生检查 " + bodyPartA.getName() + ":量血压");
    }

    @Override
    public void visit(BodyPartB bodyPartB) {
        System.out.println("内科医生检查 " + bodyPartB.getName() + ":听诊");
    }
}

// 具体访问者:化验师
public class LabTechnician implements Doctor {
    @Override
    public void visit(BodyPartA bodyPartA) {
        System.out.println("化验师检查 " + bodyPartA.getName() + ":验血");
    }

    @Override
    public void visit(BodyPartB bodyPartB) {
        System.out.println("化验师检查 " + bodyPartB.getName() + ":验尿");
    }
}

// 元素接口:身体部位
public interface BodyPart {
    String getName();
    void accept(Doctor doctor); // 接受医生
}

// 具体元素:手臂
public class BodyPartA implements BodyPart {
    @Override
    public String getName() {
        return "手臂";
    }

    @Override
    public void accept(Doctor doctor) {
        doctor.visit(this); // 接受医生,并将自身传递给医生
    }
}

// 具体元素:心脏
public class BodyPartB implements BodyPart {
    @Override
    public String getName() {
        return "心脏";
    }

    @Override
    public void accept(Doctor doctor doctor) {
        doctor.visit(this); // 接受医生,并将自身传递给医生
    }
}

// 对象结构:身体
public class Body {
    private List<BodyPart> bodyParts = new ArrayList<>();

    public void add(BodyPart bodyPart) {
        bodyParts.add(bodyPart);
    }

    public void remove(BodyPart bodyPart) {
        bodyParts.remove(bodyPart);
    }

    public void accept(Doctor doctor) {
        for (BodyPart bodyPart : bodyParts) {
            bodyPart.accept(doctor); // 让每个身体部位接受医生
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Body body = new Body(); // 创建身体对象
        body.add(new BodyPartA()); // 添加手臂
        body.add(new BodyPartB()); // 添加心脏

        Doctor internalMedicineDoctor = new InternalMedicineDoctor(); // 创建内科医生
        Doctor labTechnician = new LabTechnician(); // 创建化验师

        body.accept(internalMedicineDoctor); // 让内科医生检查身体
        body.accept(labTechnician); // 让化验师检查身体
    }
}

分析:

  • Doctor 是访问者接口,定义了访问不同身体部位的 visit 方法。
  • InternalMedicineDoctorLabTechnician 是具体访问者,分别实现了内科医生和化验师的检查逻辑。
  • BodyPart 是元素接口,定义了 accept 方法,用于接受医生。
  • BodyPartABodyPartB 是具体元素,分别代表手臂和心脏,实现了 accept 方法,将自身传递给医生。
  • Body 是对象结构,包含了所有的身体部位,并提供了 accept 方法,让每个身体部位接受医生。

输出结果:

内科医生检查 手臂:量血压
内科医生检查 心脏:听诊
化验师检查 手臂:验血
化验师检查 心脏:验尿

四、 访问者模式的优缺点

优点:

  • 分离操作 🔗!
  • 增加新操作 ➕!
  • 符合单一职责原则 👨‍⚕️!
  • 易于扩展 🆕!

缺点:

  • 增加了系统的复杂度 😫!
  • 违反了开闭原则(如果增加新的元素,需要修改所有的访问者) ❌!
  • 元素必须暴露内部状态给访问者 🙈!

五、 访问者模式的应用场景

  • 对对象结构中的对象执行不同的操作,但是你不想修改这些对象的类: 就像你想让不同的医生检查你的身体,但是你不想修改你的身体结构 🧍!
  • 需要在运行时动态地添加新的操作: 就像你想临时增加一个检查项目,比如做核磁共振 🧲!
  • 操作和对象结构之间的关系比较稳定: 就像检查项目和身体之间的关系比较稳定 🏥!

六、 总结

  • 访问者模式就像让不同的"医生(访问者)"来"检查(访问)"你的"身体(元素)",并执行不同的检查项目! 👨‍⚕️+🏥
  • 优点是分离操作、增加新操作、符合单一职责原则、易于扩展! 👍
  • 缺点是增加复杂度、违反开闭原则、元素必须暴露内部状态! 👎
  • 适用于需要对对象结构中的对象执行不同的操作,但是你不想修改这些对象的类的场景! 🎯

希望这个例子能让你彻底理解访问者模式! 💯 祝你学习愉快! 😄

相关推荐
攻城狮7号1 小时前
【第14节】C++设计模式(行为模式)-Strategy (策略)模式
c++·设计模式·策略模式
BUG研究员_2 小时前
MQ消息丢失解决方案
java·开发语言
m0_748238782 小时前
20.<Spring图书管理系统①(登录+添加图书)>
java·后端·spring
攻城狮7号4 小时前
【第13节】C++设计模式(行为模式)-Template(模板)模式
c++·设计模式·模板方法模式
high20114 小时前
【Java 基础】-- 设计模式
java·单例模式·设计模式
yuanpan4 小时前
23种设计模式之《备忘录模式(Memento)》在c#中的应用及理解
开发语言·设计模式·c#·备忘录模式
LUCIAZZZ4 小时前
Java中的设计模式违反了哪些设计原则
java·开发语言·spring boot·后端·spring·设计模式
ashane13144 小时前
设计模式说明
java
powerfulzyh5 小时前
StarRocks-fe工程在Cursor中不能识别为Java项目
java·开发语言
一点多余.5 小时前
Spring Boot 自动装配深度解析与实践指南
xml·java·spring·自动装配