当前位置: 首页 > news >正文

设计模式笔记_行为型_访问者模式

1. 访问者模式介绍

访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不改变对象结构的前提下,定义作用于这些对象的新操作。访问者模式将操作的逻辑从对象结构中分离出来,使得你可以在运行时动态地添加新的操作

类比场景:想象一下,你有一个博物馆,里面有不同的展品(对象结构):绘画、雕塑等。当有不同的访客(访问者,比如艺术爱好者、学生等)来参观时,他们可能希望对展品进行不同的处理或观察(操作)。访问者模式就像是让这些访客带着自己的需求来参观博物馆,而博物馆本身无需改变展品的展示方式。当有新的访问者要进行新的操作时,只需要新增一个访问者即可。

结构组成:

  1. Visitor(访问者接口):定义访问者可以执行的操作;对每种元素类型都有一个方法。
  2. ConcreteVisitor(具体访问者):实现Visitor接口,定义每个元素的具体访问行为。
  3. Element(元素接口):被访问者接口,定义接受访问者的方法。
  4. ConcreteElement(具体元素):实现Element接口,具体定义接受访问者的行为。
  5. Object Structure:包含元素的集合,提供一个可以遍历这些元素的高层接口,并让访问者访问它们。

优缺点分析:

  • 优点
    • 新增操作方便:可以在不修改对象结构的情况下增加新的操作(通过新增visitor实现)。
    • 符合单一职责原则:将不同的操作分离到不同的访问者中。
    • 扩展性好:可以很方便地增加新的访问者。
  • 缺点
    • 对象结构必须稳定:如果对象结构经常改变,维护成本会很高(每个visitor里定义了对所有元素的访问,如果元素发生改变,需要修改所有visitor)。
    • 具体元素更复杂:每个具体元素都需要实现接受访问者的方法。
    • 可能导致类爆炸:如果元素和访问者种类很多,会导致类数量激增。

适用场景:

  • 当对象结构较为稳定,且需要在此结构上定义新的操作时。
  • 当需要对一个对象结构中的对象进行很多不同且不相关的操作时。

2. 代码演示

场景:学生和艺术爱好者(visitor)去博物馆(objectStructure)参观绘画和雕像(element),各类人行为不同。

Visitor(访问者接口):

// Visitor接口:定义一个访问者可以执行的操作
// 包含了对所有具体元素的访问方法
public interface Visitor {void visit(Painting painting);void visit(Sculpture sculpture);
}

ConcreteVisitor(具体访问者):

//具体访问者: 实现Visitor接口,用于定义某种操作
//艺术爱好者的行为
public class ArtLoverVisitor implements Visitor {@Overridepublic void visit(Painting painting) {System.out.println("ArtLoverVisitor visit painting: " + painting.getName());}@Overridepublic void visit(Sculpture sculpture) {System.out.println("ArtLoverVisitor visit sculpture: " + sculpture.getName());}
}//学生的行为
public class StudentVisitor implements Visitor {@Overridepublic void visit(Painting painting) {System.out.println("StudentVisitor visit painting: " + painting.getName());}@Overridepublic void visit(Sculpture sculpture) {System.out.println("StudentVisitor visit sculpture: " + sculpture.getName());}
}

Element(元素接口)

// Element接口:被访问对象,定义接受访问者的接口
public interface Exhibit {void accept(Visitor visitor);
}

ConcreteElement(具体元素):

// 具体元素: 实现Element接口,定义接受访问者的操作
// 绘画
public class Painting implements Exhibit {private String name;public Painting(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}//雕像
public class Sculpture implements Exhibit {private String name;public Sculpture(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}

Object Structure:

// ObjectStructure:维护元素对象列表,并提供高层方法来遍历操作这些对象
public class Museum {private List<Exhibit> exhibits = new ArrayList<>();public void addExhibit(Exhibit exhibit) {exhibits.add(exhibit);}public void showExhibits(Visitor visitor) {for (Exhibit exhibit : exhibits) {exhibit.accept(visitor);}}
}

客户端:

public class VisitorClientDemo {public static void main(String[] args) {Museum museum = new Museum();museum.addExhibit(new Sculpture("The Thinker"));museum.addExhibit(new Painting("Starry Night"));Visitor visitor1 = new ArtLoverVisitor();museum.showExhibits(visitor1);Visitor visitor2 = new StudentVisitor();museum.showExhibits(visitor2);}
}

对应的类图:

扩展:

上述示例中,将操作(学生/艺术爱好者的行为) 从对象结构(绘画/雕塑等展览)中分离出来了,后续若需添加新的操作(历史专家的行为),只需要新增对应的visitor(HistorianVisitor) 即可。

http://www.lryc.cn/news/624526.html

相关文章:

  • 【arXiv2025】计算机视觉|FGA:即插即用!让你的模型精准预测人群密度!
  • 微信小程序通过uni.chooseLocation打开地图选择位置,相关设置及可能出现的问题
  • 【深度学习】pytorch深度学习框架的环境配置
  • CPTS---Active 复现
  • 如何部署 PHPWind 8.5 UTF8 论坛?从下载到安装全流程(附安装包下载)
  • 20250818在荣品的PRO-RK3566开发板跑Buildroot的时候使用在线秒表https://tool.hiofd.com/stopwatch/
  • Python循环语句 从入门到精通
  • 【运维进阶】LNMP + WordPress 自动化部署实验
  • 第十六届蓝桥杯青少组C++省赛[2025.8.10]第二部分编程题(5、环形取硬币游戏)
  • Baumer高防护相机如何通过YoloV8深度学习模型实现网球运动员和网球速度的检测分析(C#代码UI界面版)
  • Opsqueue:为重负载而生的轻量级批处理队列,已开源!
  • Bellman-Ford与spfa算法简介
  • ARM架构下的cache transient allocation hint以及SMMUv2的TRANSIENTCFG配置详解
  • 大数据时代时序数据库选型指南:深度解析与 Apache IoTDB 实践
  • C++对象的内存布局
  • 一般情况下,python函数都会返回对象,但有时只调用一个函数,这是在修改这个信息
  • 【笔记】扩散模型(一一):Stable Diffusion XL 理论与实现
  • STRIDE威胁模型
  • 图像分类精度评价的方法——误差矩阵、总体精度、用户精度、生产者精度、Kappa 系数
  • 论文阅读 2025-8-9 [DiC, DropKey]
  • promise async await总结
  • linux中的hostpath卷与nfs卷以及静态持久卷的区别
  • 大数据计算引擎(二)——Flink
  • 使用AWS S3 + Lambda + MediaConvert 实现上传视频文件并自动转码
  • 一套GoldenGate → Kafka → Flink → MySQL 的端到端增量同步方案
  • 「Flink」业务搭建方法总结
  • 基于Flink CDC实现联系人与标签数据实时同步至ES的实践
  • Ansible文件部署与大项目多主机管理
  • 大数据开发面试题:美团秋招一面
  • 数据赋能(401)——大数据——持续学习与优化原则