笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 设计模式

    • 简介

    • 原则

    • UML

    • 创建型

    • 结构型

    • 行为型

      • 模板模式
      • 命令模式
      • 访问者模式
        • 简介
        • 访问者模式
          • 代码示例
        • 说明
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 解释器模式
      • 状态模式
      • 策略模式
      • 职责链模式
  • JVM 详解

  • Linux

  • Redis

  • 分布式锁

  • Shiro

  • Gradle

  • Java 进阶
  • 设计模式
  • 行为型
EasT-Duan
2023-11-23
目录

访问者模式

欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

# 简介

访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

主要将数据结构与数据操作分离,解决 数据结构和操作耦合性问题。

访问者模式的基本工作原理是:在被访问的类里面加一个对外提供接待访问者的接口。

访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时需要避免让这些操作 "污染" 这些对象的类,可以选用访问者模式解决。

Visitor:是抽象访问者,为该对象结构中的 ConcreteElement 的每一个类声明一个 visit 操作。

ConcreteVisitor:是一个具体的访问值实现每个有 Visitor 声明的操作,是每个操作实现的部分。

ObjectStructure 能枚举它的元素,可以提供一个高层的接口,用来允许访问者访问元素。

Element:定义一个 accept 方法,接收一个访问者对象。

ConcreteElement:为具体元素,实现了 accept 方法。

# 访问者模式

一个例子:将人分为男人和女人,对歌手进行测评,当看完某个歌手表演后,得到他们对该歌手 不同的评价(评价有不同的种类,比如 成功、失败等),请使用访问者模式来说实现。

# 代码示例

package visitor;

/**
 * 访问者接口
 */
public interface Visitor {
    //得到男性的测评
    void getManResult(ConcreteElementA man);

    //得到女的测评
    void getWomanResult(ConcreteElementB woman);
}
1
2
3
4
5
6
7
8
9
10
11
12
package visitor;

/**
 * 定义个接受访问者的方法
 */
public interface Element {

    /**
     * 提供一个方法,让访问者可以访问
     * @param visitor   访问者,传递具体的实现
     */
    void accept(Visitor visitor);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package visitor;

/**
 * 男性
 * 双分派,不管类怎么变化,我们都能找到期望的方法运行。双分派意味着得到执行的操作取决于请求的种类和两个接收者的类型
 */
public class ConcreteElementA implements Element {

    @Override
    public void accept(Visitor visitor) {
        visitor.getManResult(this);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package visitor;

/**
 * 女性
 */
public class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.getWomanResult(this);
    }
}
1
2
3
4
5
6
7
8
9
10
11
package visitor;

/**
 * 访问者的实现类
 */
public class ConcreteVisitorA implements Visitor {
    public void getManResult(ConcreteElementA man) {
        System.out.println(" 男人给的评价该歌手很成功 !");
    }

    public void getWomanResult(ConcreteElementB woman) {
        System.out.println(" 女人给的评价该歌手很成功 !");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package visitor;

/**
 * 访问者的实现类
 */
public class ConcreteVisitorB implements Visitor {
    public void getManResult(ConcreteElementA man) {
        System.out.println(" 男人给的评价该歌手很失败 !");
    }

    public void getWomanResult(ConcreteElementB woman) {
        System.out.println(" 女人给的评价该歌手很失败 !");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package visitor;

/**
 * 对象结构,包含了一个元素列表,并提供了添加、删除元素和接受访问者的方法
 */
public class ObjectStructure {
    private List<Element> elements = new LinkedList<>();

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

    public void removeElement(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package visitor;

public class Client {
    public static void main(String[] args) {
        //创建ObjectStructure
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(new ConcreteElementA());     // 加入一个男人
        objectStructure.addElement(new ConcreteElementB());     // 加入一个女人
        // 创建一个访问者
        Visitor visitor = new ConcreteVisitorA();// 评价成功的
        // 调用  objectStructure.accept(visitor) 时,其实调用的是 Visitor 中的方法,这里发生一次分派,然后在 Visitor 实现类的内部根据
        // 传递进来的 Element 调用 实现类的 accept() 方法,这里发生了第二次分派
        objectStructure.accept(visitor);


        visitor = new ConcreteVisitorB();// 评价失败的
        objectStructure.accept(visitor);
        visitor = new ConcreteVisitorC();
        objectStructure.accept(visitor);


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

# 说明

  • 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常。

  • 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统 。

  • 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变更比较困难。

  • 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素。

因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的。

#设计模式
上次更新: 2025/04/12, 05:37:39
命令模式
迭代器模式

← 命令模式 迭代器模式→

最近更新
01
Reactor 核心
02-24
02
前置条件
10-30
03
计算机网络
09-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式