设计模式——访问者模式

访问者模式

定义

封装一些的对于某种数据结构中的各元素的操作,它可以在不改变数据的前提下定义作用于这些元素的新的操作

访问者模式(Visitor pattern)是相对简单的模式,也可以作为迭代器模式的补充

优缺点、应用场景

优点

  1. 符合单一职责原则。具体角色负责数据的存储,而访问者对象Visitor负责报表的展示,职责明确区分开来
  2. 优秀的拓展性。由于单一职责,继续增加visitor对数据操作是容易的。
  3. 灵活性非常高。可以对不同的角色做定制化处理。

缺点

  1. 具体角色对访问者公布细节。即visitor关注了具体角色的内部细节,违反了迪米特法则。
  2. 具体角色变更更困难。具体角色属性的变动会导致visitor中对应角色的逻辑变更。
  3. 违背了依赖倒置原则。visitor依赖的是具体的角色,而不是抽象,破坏了依赖倒置原则。在面向对象编程中,直接操作具体角色会造成拓展困难。

应用场景

  1. 一个对象结构包含很多类对象,它们有不同的接口,又需要对这些对象实施一些依赖于其具体类的操作。
  2. 需要对一个对象结构中的对象进行很多不同并且不相关的操作。

模拟场景

打印报表。还原在Van的地♂牢中的场景

非访问者模式

演员的抽象和实现

/*** 我们都是演员 抽象类*/
public abstract class Actors {public final static int SLAVE = 0;public final static int MASTER = 1;private String name;private int power;private int position;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPower() {return power;}public void setPower(int power) {this.power = power;}public int getPosition() {return position;}public void setPosition(int position) {this.position = position;}/*** 打印演员的信息*/public void report() {String info = "姓名:" + this.name + "\t";info += "身份:" + (this.position == SLAVE ? "平家boy" : "Dungeon Master") + "\t";info += "权力:" + this.power + "\t";info += this.getOtherInfo();System.out.println(info);}/*** 拼装其他演员的信息** @return 信息*/protected abstract String getOtherInfo();
}/*** 地牢统治者*/
public class DungeonMaster extends Actors {/*** 职责*/private String performance;public String getPerformance() {return performance;}public void setPerformance(String performance) {this.performance = performance;}@Overrideprotected String getOtherInfo() {return "职责:" + this.performance + "\t";}
}/*** 平家Boy*/
public class PingjiaBoy extends Actors {/*** 工作内容*/private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}@Overrideprotected String getOtherInfo() {return "工作内容:" + this.job + "\t";}
}

入口类方法

public static void mockActors() {List<Actors> actors = new ArrayList<>();// 马凯PingjiaBoy makai = new PingjiaBoy();makai.setName("马凯");makai.setPosition(Actors.SLAVE);makai.setPower(0);makai.setJob("Show~ Yes Sir");// 吾作PingjiaBoy wuzuo = new PingjiaBoy();wuzuo.setName("吾作");wuzuo.setPosition(Actors.SLAVE);wuzuo.setPower(0);wuzuo.setJob("Show~ Yes Sir");// 地牢统治者DungeonMaster van = new DungeonMaster();van.setName("Van");van.setPosition(Actors.MASTER);van.setPower(10000);van.setPerformance("Take it boy");actors.add(van);actors.add(makai);actors.add(wuzuo);for (Actors actor : actors) {actor.report();}
}

结果

在这里插入图片描述

访问者模式

小结

  1. 三个变动。删除report()方法,增加accept()方法,删除getOtherInfo()方法
  2. 即Actors都可以被访问者访问

UML图

在这里插入图片描述

演员的抽象和实现

/*** 我们都是演员 抽象类*/
public abstract class Actors {public final static int SLAVE = 0;public final static int MASTER = 1;private String name;private int power;private int position;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPower() {return power;}public void setPower(int power) {this.power = power;}public int getPosition() {return position;}public void setPosition(int position) {this.position = position;}/*** 拼装其他演员的信息*/public abstract void accept(IVisitor visitor);
}/*** 地牢统治者*/
public class DungeonMaster extends Actors {/*** 职责*/private String performance;public String getPerformance() {return performance;}public void setPerformance(String performance) {this.performance = performance;}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}
}/*** 平家Boy*/
public class PingjiaBoy extends Actors {/*** 工作内容*/private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}@Overridepublic void accept(IVisitor visitor) {visitor.visit(this);}
}

访问者抽象和实现

/*** 观众老爷 访问者接口*/
public interface IVisitor {/*** 定义可以访问的平家boy*/void visit(PingjiaBoy pingjiaBoy);/*** 定义可以访问的master*/void visit(DungeonMaster master);
}/*** 访问者实现*/
public class Visitor implements IVisitor {@Overridepublic void visit(PingjiaBoy pingjiaBoy) {System.out.println(getPingjiaBoyInfo(pingjiaBoy));}@Overridepublic void visit(DungeonMaster master) {System.out.println(getDungeonMasterInfo(master));}/*** 组装演员的基本信息** @param actor 演员对象* @return 演员对象的基本信息*/private String getBaseInfo(Actors actor) {String info = "姓名:" + actor.getName() + "\t";info += "身份:" + (actor.getPosition() == Actors.SLAVE ? "平家boy" : "Dungeon Master") + "\t";info += "权力:" + actor.getPower() + "\t";return info;}/*** 组装master的信息** @param master master对象* @return master的信息*/private String getDungeonMasterInfo(DungeonMaster master) {String info = this.getBaseInfo(master);String masterInfo = "职责:" + master.getPerformance() + "\t";return info + masterInfo;}/*** 组装平家boy的信息** @param pingjiaBoy 平家boy对象* @return 平家boy的信息*/private String getPingjiaBoyInfo(PingjiaBoy pingjiaBoy) {String info = this.getBaseInfo(pingjiaBoy);String pingjiaBoyInfo = "工作内容:" + pingjiaBoy.getJob() + "\t";return info + pingjiaBoyInfo;}
}

入口类方法

public static void visitor() {List<Actors> actors = new ArrayList<>();// 马凯PingjiaBoy makai = new PingjiaBoy();makai.setName("马凯");makai.setPosition(Actors.SLAVE);makai.setPower(0);makai.setJob("Show~ Yes Sir");// 吾作PingjiaBoy wuzuo = new PingjiaBoy();wuzuo.setName("吾作");wuzuo.setPosition(Actors.SLAVE);wuzuo.setPower(0);wuzuo.setJob("Show~ Yes Sir");// 地牢统治者DungeonMaster van = new DungeonMaster();van.setName("Van");van.setPosition(Actors.MASTER);van.setPower(10000);van.setPerformance("Take it boy");actors.add(van);actors.add(makai);actors.add(wuzuo);IVisitor visitor = new Visitor();for (Actors actor : actors) {actor.accept(visitor);}
}

结果

在这里插入图片描述

参考书籍

秦小波《设计模式之禅》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/23166.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解析浏览器Cookie(图文码教学)

深入解析浏览器Cookie 前言一、什么是 Cookie?二、Cookie的特点二、如何创建 Cookie&#xff1f;三、服务器如何获取 Cookie四、Cookie 值的修改4.1 方案一4.2 方案二 五、浏览器查看 Cookie六、Cookie 生命控制七、Cookie 有效路径 Path 的设置八、案例&#xff1a;Cookie 练…

Linux学习之环境变量

环境变量是每个Shell打开就能获取到的变量&#xff0c;即一打开终端就已经初始化的变量。set、env和declare都可以查看变量的值。按照可以查看信息的范围从小到大是env<set<declare。 env只能显示全局变量。 set可以输出所有的变量&#xff0c;包括全局变量和局部变量。…

软考高级架构师笔记-9系统架构

目录 1. 前文回顾 & 考情分析2. 软件架构概述3. 软件架构风格3.1 层次架构风格3.2 面向服务架构风格4. 软件架构复用5. 特定领域软件体系结构DSSA6. ABSD7. 质量属性8. 架构评估9 结语1. 前文回顾 & 考情分析 前文回顾: 软考高级架构师笔记-1计算机硬件软考高级架构师…

IDEA项目报错随笔记录

文章目录 1. 无效的源发行版: 172. java: 无法访问org.springframework.boot.SpringApplication3. java: 程序包org.junit.jupiter.api不存在4. SpringbootTest注解爆红5. maven命令安装本地jar包报错&#xff1a;[拒绝访问]5. maven命令安装本地jar包报错&#xff1a;Unknown …

Kafka 概述、Filebeat+Kafka+ELK

Kafka 概述、FilebeatKafkaELK 一、为什么需要消息队列&#xff08;MQ&#xff09;1、使用消息队列的好处2、消息队列的两种模式 二、Kafka 定义1、Kafka 简介2、Kafka 的特性3、Kafka 系统架构 三、部署 kafka 集群1.下载安装包2.安装 Kafka3.Kafka 命令行操作 四、Kafka 架构…

吴恩达机器学习2022-Jupyter-机器学习实例

1 可选实验: 特征工程和多项式回归 1.1 目标 在这个实验室里: 探索特征工程和多项式回归&#xff0c;它可以让你使用线性回归机制来适应非常复杂&#xff0c;甚至非常非线性的函数。 1.2 工具 您将利用在以前的实验中开发的函数以及matplotlib和NumPy。 2 特征工程与多项式…

使用Gradio库进行交互式数据可视化:Timeseries模块介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

【Hippo4j监控Web容器Tomcat线程池】

&#x1f680; 线程池管理工具-Hippo4j &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#…

traceId跟踪请求全流程日志

一个系统被拆分成N多个模块&#xff0c;这些模块负责不同的功能&#xff0c;组合成一套系统&#xff0c;最终可以提供丰富的功能。在这种分布式架构中&#xff0c;一次请求往往需要涉及到多个服务&#xff0c;如下图&#xff1a; 服务之间的调用错综复杂&#xff0c;对于维护的…

JVM系列(6)——类加载器详解双亲委派

一、类加载器 类加载器是一个负责加载类的对象&#xff0c;用于实现类加载过程中的加载这一步。 主要作用就是加载 Java 类的字节码&#xff08; .class 文件&#xff09;到 JVM 中&#xff08;在内存中生成一个代表该类的 Class 对象&#xff09;。 加载过程可以看 JVM系列&a…

《面试1v1》Kafka基础

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

RabbitMQ之交换机

RabbitMQ之交换机 1. Exchanges1.1 Exchanges 概念1.2 Exchanges 的类型1.3 无名 exchange 2. 临时队列3. 绑定&#xff08;bindings&#xff09;4. Fanout4.1 Fanout 介绍4.2 Fanout 实战 5. Direct exchange5.1 Direct exchange 介绍5.2 多重绑定5.3 实战 6. Topics6.1 之前类…