行为型模式:访问者模式
文章首发: 行为型模式:访问者模式
十一大行为型模式之十一:访问者模式。
简介
姓名 :访问者模式
英文名 :Visitor Pattern
价值观 :来访者便是客,招待就是
个人介绍 : Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates. 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。 (来自《设计模式之禅》)
你要的故事
先声明一下,下面故事全瞎编的。。。
我们是否还记得 N 年前反腐开始的时候,有一段时间提倡官员宴请吃饭只能几菜几汤,不能超出。我记得那会刚读大一,军事理论的老师说到这个问题,也发表了他的一些想法,他觉得这么做比较刻板。今天的故事就和宴请有关。现在中国企业发展越来越大,在社会中担任的责任也越来越大,政府也越来越重视企业,官员去参观企业是常有的事,而企业宴请官员也变得格外的常见。
故事的背景就是企业宴请各级官员。不同级别的官员宴请的菜式就不一样,每家企业的菜式丰富程度也不一样。我们这里的访问对象就用 Alibaba 和 Tencent 这 2 家公司,而访问者就用郭嘉领导人和省领导人做举例。这 2 家公司都跟喜来登酒店合作,Alibaba 合作方案是:宴请省级领导人及以下官员则十菜一汤,宴请郭嘉领导人及以上官员则十四菜两汤;Tencent 合作方案是:宴请省领导人及以下官员则八菜一汤,宴请郭嘉领导人及以上官员则十六菜两汤。
下面看看如何用访问者模式来实现上面的故事。
首先定义一个抽象类:企业。企业有一个共有的特性就是接受上级领导的访问。
/** * 企业 */ abstract class Company { public abstract void accept(Vistor vistor); }
上面故事我们举例了 2 家企业,分别是 Alibaba 和 Tencent,这里实现这 2 家公司的宴请方案,并实现接待访问者方法。
Alibaba 宴请郭嘉领导人及以上官员是十四菜两汤,宴请省领导及以下是十菜一汤。
/** * Alibaba 企业 */ class AlibabaCompany extends Company { @Override public void accept(Vistor vistor) { vistor.visit(this); } public String entertainBelowProvincialLeader(String leader) { return "Alibaba 接待" + leader + ":十菜一汤"; } public String entertainAboveNationalLeader(String leader) { return "Alibaba 接待" + leader + ":十四菜两汤"; } }
Tencent 宴请郭嘉领导人及以上是十六菜两汤,宴请省领导及以下是八菜一汤。
/** * Tencent 企业 */ class TencentCompany extends Company { @Override public void accept(Vistor vistor) { vistor.visit(this); } public String entertainBelowProvincialLeader(String leader) { return "Tencent 接待" + leader + ":八菜一汤"; } public String entertainAboveNationalLeader(String leader) { return "Tencent 接待" + leader + ":十六菜两汤"; } }
这里定义访问者接口,访问者接口有 2 个方法,分别是访问 Alibaba 企业和访问 Tencent 企业。
/** * 访问者接口 */ interface Vistor { void visit(AlibabaCompany alibabaCompany); void visit(TencentCompany tencentCompany); }
上面故事中有 2 个访问者,一个是郭嘉领导人,另一个是省领导人,因为不同企业对应不同访问者有不同的宴请方案,所以这里访问企业是需要调用对应企业的宴请方式。
省领导人访问企业时,需要调用企业对省领导及以下官员的宴请方案,为entertainBelowProvincialLeader()
/** * 省领导访问 */ class ProvincialLeaderVistor implements Vistor { @Override public void visit(AlibabaCompany alibabaCompany) { System.out.println(alibabaCompany.entertainBelowProvincialLeader("省领导")); } @Override public void visit(TencentCompany tencentCompany) { System.out.println(tencentCompany.entertainBelowProvincialLeader("省领导")); } }
郭嘉领导人访问企业时,需要调用企业对郭嘉领导人的宴请方案,为entertainAboveNationalLeader()
/** * 郭嘉领导访问 */ class NationalLeaderVistor implements Vistor { @Override public void visit(AlibabaCompany alibabaCompany) { System.out.println(alibabaCompany.entertainAboveNationalLeader("省领导")); } @Override public void visit(TencentCompany tencentCompany) { System.out.println(tencentCompany.entertainAboveNationalLeader("郭嘉领导")); } }
上面是访问者和被访问者的代码,因为企业是在喜来登酒店宴请领导人,所以这里还需要一个酒店,酒店里面有企业合作的名单,以及负责宴请各路领导的方法提供。
/** * 酒店 */ class Hotel { private List<Company> companies = new ArrayList<>(); public void entertain(Vistor vistor) { for (Company company : companies) { company.accept(vistor); } } public void add(Company company) { companies.add(company); } }
下面提供测试代码,看看运行的结果怎样。
public class VisitorTest { public static void main(String[] args) { AlibabaCompany alibabaCompany = new AlibabaCompany(); TencentCompany tencentCompany = new TencentCompany(); ProvincialLeaderVistor provincialLeaderVistor = new ProvincialLeaderVistor(); NationalLeaderVistor nationalLeaderVistor = new NationalLeaderVistor(); Hotel xilaideng = new Hotel(); xilaideng.add(alibabaCompany); xilaideng.add(tencentCompany); xilaideng.entertain(provincialLeaderVistor); xilaideng.entertain(nationalLeaderVistor); } } 打印结果: Alibaba 接待省领导:十菜一汤 Tencent 接待省领导:八菜一汤 Alibaba 接待郭嘉领导:十四菜两汤 Tencent 接待郭嘉领导:十六菜两汤
完整的访问者模式代码已经呈现,花 1 分钟思考一番,理解整个代码后我们来看看下面的总结。
总结
访问者模式有比较好的扩展性,看看访问者代码,我们如果要新增一个访问者:市领导人,只需新增市领导人类,便可实现。当然也有它不好的地方,就是把被访问者暴露给访问者,使得访问者可以直接了解被访问者的所有东西。明白了优缺点,才能更好的在实际中运用,一般访问者模式运用于要求遍历多个不同的对象的场景。
推荐阅读
设计模式系列文章持续更新中,欢迎关注公众号 LieBrother,一起交流学习。
公众号后台回复『大礼包』获取 Java、Python、IOS 等教程 加个人微信备注『教程』获取架构师、机器学习等教程

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一次分表踩坑实践的探讨
前言 之前不少人问我“能否分享一些分库分表相关的实践”,其实不是我不分享,而是真的经验不多?;和大部分人一样都是停留在理论阶段。 不过这次多少有些可以说道了。 先谈谈背景,我们生产数据库随着业务发展量也逐渐起来;好几张单表已经突破亿级数据,并且保持每天 200+W 的数据量增加。 而我们有些业务需要进行关联查询、或者是报表统计;在这样的背景下大表的问题更加突出(比如一个查询功能需要跑好几分钟)。 可能很多人会说:为啥单表都过亿了才想方案解决?其实不是不想,而是由于历史原因加上错误预估了数据增长才导致这个局面。总之原因比较复杂,也不是本次讨论的重点。 临时方案 由于需求紧、人手缺的情况下,整个处理的过程分为几个阶段。 第一阶段应该是去年底,当时运维反应 MySQL 所在的主机内存占用很高,整体负载也居高不下,导致整个 MySQL 的吞吐量明显降低(写入、查询数据都明显减慢)。 为此我们找出了数据量最大的几张表,发现大部分数据量在7/8000W 左右,少数的已经突破一亿。 通过业务层面进行分析发现,这些数据多数都是用户产生的一些日志型数据,而且这些数据在业务上并不是强相关的,甚至两三个月...
- 下一篇
深入理解 React 的 Virtual DOM
React在前端界一直很流行,而且学起来也不是很难,只需要学会JSX、理解State和Props,然后就可以愉快的玩耍了,但想要成为React的专家你还需要对React有一些更深入的理解,希望本文对你有用。 这是Choerodon的一个前端页面 在复杂的前端项目中一个页面可能包含上百个状态,对React框架理解得更精细一些对前端优化很重要。曾经这个页面点击一条记录展示详情会卡顿数秒,而这仅仅是前端渲染造成的。 为了能够解决这些问题,开发者需要了解React组件从定义到在页面上呈现(然后更新)的整个过程。 React在编写组件时使用混合HTML和JavaScript的一种语法(称为JSX)。 但是,浏览器对JSX及其语法一无所知,浏览器只能理解纯JavaScript,因此必须将JSX转换为HTML。 这是一个div的JSX代码,它有一个类和一些内容: <div className='cn'> 文本 </div> 在React中将这段jsx变成普通的js之后它就是一个带有许多参数的函数调用: React.createElement( 'div', { classNa...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- Hadoop3单机部署,实现最简伪集群
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题