Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • JavaSE

  • JavaEE

  • Linux

  • MySQL

  • NoSQL

  • Python

  • Python模块

  • 机器学习

  • 设计模式

    • 设计模式的概念
    • 创建型模式
    • 单例(Singleton)模式
    • 原型(Prototype)模式
    • 工厂(Factory)模式
    • 建造者(Builder)模式
    • 结构型模式(Structural Pattern)
    • 适配器模式(Adapter Pattern)
    • 桥接模式(Bridge Pattern)
    • 装饰器模式(Decorator、Wrapper(包装) Pattern)
    • 代理模式(Proxy Pattern)
    • 外观模式(Facade Pattern)
    • 组合模式(Composite Pattern)
    • 享元模式(Flyweight Pattern)
    • 行为型模式(Behavioral Patterns)
    • 模板方法(Template Method)
    • 策略(Strategy)模式
    • 状态(State)模式
    • 中介者(Mediator)模式
    • 观察者(Observer)模式
    • 备忘录(Memento)模式
    • 解释器(Interpreter)模式
    • 命令(Command)模式
    • 迭代器(Iterator)模式
    • 访问者(Visitor)模式
      • 应用场景
      • 注意事项和细节
    • 职责链(Chain of Responsibility)模式
    • 总结
  • 传智健康

  • 畅购商城

  • 博客项目

  • JVM

  • JUC

  • Golang

  • Kubernetes

  • 硅谷课堂

  • C

  • 源码

  • 神领物流

  • RocketMQ

  • 短链平台

  • 后端
  • 设计模式
Iekr
2023-12-10
目录

访问者(Visitor)模式

# 访问者(Visitor)模式

将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。

  • 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit () ,该操作中的参数类型标识了被访问的具体元素。
  • 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  • 抽象元素(Element)角色:声明一个包含接受操作 accept () 的接口,被接受的访问者对象作为 accept () 方法的参数。
  • 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept () 操作,其方法体通常都是 visitor.visit (this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
  • 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。

image-20231210223236628

抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit () ,该操作中的参数类型标识了被访问的具体元素。

/**
 * 升级包的接口
 */
public interface Visitor {
    void visitDisk(Disk disk);

    void visitCpu(CPU cpu);

}
1
2
3
4
5
6
7
8
9

具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。

/**
 * 升级包可以更改指令
 */
public class UpdatePackage implements Visitor {

    private String ext;

    public UpdatePackage(String ext) {
        this.ext = ext;
    }

    @Override
    public void visitDisk(Disk disk) {
        disk.command += "联网存储中..." + ext;
    }

    @Override
    public void visitCpu(CPU cpu) {
        // 这里只改指令属性
        cpu.command += "联网查询中..." + ext;
        // 装饰模式 改方法
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

抽象元素(Element)角色:声明一个包含接受操作 accept () 的接口,被接受的访问者对象作为 accept () 方法的参数。

public abstract class HardWare {
    String command; // 封装硬件的处理指令

    public HardWare(String command) {
        this.command = command;
    }

    public void work() {
        System.out.println("收到指令:" + command);
    }

    // 定义接受软件升级包的方法,这个方法应该具体硬件去实现
    public abstract void accept(Visitor visitor);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept () 操作,其方法体通常都是 visitor.visit (this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。

public class CPU extends HardWare {
    public CPU(String command) {
        super(command);
    }

    public void work() {
        System.out.println("CPU 收到指令:" + command);
    }

    @Override
    public void accept(Visitor visitor) {
        // 给升级包提供一个改cpu指令等信息的办法
        visitor.visitCpu(this);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Disk extends HardWare {

    public Disk(String command) {
        super(command);
    }

    public void work() {
        System.out.println("Disk收到指令:" + command);
    }

    @Override
    public void accept(Visitor visitor) {
        // 给升级包提供一个改disk指令等信息的办法
        visitor.visitDisk(this);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。

public class XiaoAi {
    private CPU cpu = new CPU("武汉天气");
    private Disk disk = new Disk("武汉天气");

    void answerQuestion() {
        cpu.work();
        disk.work();
    }


    // 接受升级包
    public void acceptUpdate(Visitor aPackage) {
        // 访问模式
        // 升级
        aPackage.visitCpu(cpu);
        aPackage.visitDisk(disk);

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

测试

public class MainTest {
    public static void main(String[] args) {
        XiaoAi xiaoAi = new XiaoAi();
        xiaoAi.answerQuestion();

        // 升级 cpu联网处理指令 并保存历史数据到云端
        UpdatePackage updatePackage = new UpdatePackage("联网增强功能");
        xiaoAi.acceptUpdate(updatePackage);
        xiaoAi.answerQuestion();
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 应用场景

什么场景用到?

  • 在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了 “开闭原则”。
  • 违反依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类
  • 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性
  • 应用于对象结构相对稳定,但其操作算法经常变化的程序。
  • Spring 反射工具中的 MethodVisitor 是什么?

# 注意事项和细节

优点:

  1. 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高
  2. 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统

缺点:

  1. 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变更比较困难
  2. 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素
  3. 因此, 如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么 访问者模式就是比较合适的.
编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02
迭代器(Iterator)模式
职责链(Chain of Responsibility)模式

← 迭代器(Iterator)模式 职责链(Chain of Responsibility)模式→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式