行为型模式:访问者模式
文章首发:
行为型模式:访问者模式
十一大行为型模式之十一:访问者模式。
简介
姓名 :访问者模式
英文名 :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 entertainprovincialleader() { return "alibaba 接待省领导:十菜一汤"; } public string entertainnationalleader() { return "alibaba 接待郭嘉领导:十四菜两汤"; } }
tencent 宴请郭嘉*是十六菜两汤,宴请省领导是八菜一汤。
/** * tencent 企业 */ class tencentcompany extends company { @override public void accept(vistor vistor) { vistor.visit(this); } public string entertainprovincialleader() { return "tencent 接待省领导:八菜一汤"; } public string entertainnationalleader() { return "tencent 接待郭嘉领导:十六菜两汤"; } }
这里定义访问者接口,访问者接口有 2 个方法,分别是访问 alibaba 企业和访问 tencent 企业。
/** * 访问者接口 */ interface vistor { void visit(alibabacompany alibabacompany); void visit(tencentcompany tencentcompany); }
上面故事中有 2 个访问者,一个是郭嘉*,另一个是省*,因为不同企业对应不同访问者有不同的宴请方案,所以这里访问企业是需要调用对应企业的宴请方式。
省*访问企业时,需要调用企业对省*的宴请方案,为entertainprovincialleader()
/** * 省领导访问 */ class provincialleadervistor implements vistor { @override public void visit(alibabacompany alibabacompany) { system.out.println(alibabacompany.entertainprovincialleader()); } @override public void visit(tencentcompany tencentcompany) { system.out.println(tencentcompany.entertainprovincialleader()); } }
郭嘉*访问企业时,需要调用企业对郭嘉*的宴请方案,为entertainnationalleader()
/** * 郭嘉领导访问 */ class nationalleadervistor implements vistor { @override public void visit(alibabacompany alibabacompany) { system.out.println(alibabacompany.entertainnationalleader()); } @override public void visit(tencentcompany tencentcompany) { system.out.println(tencentcompany.entertainnationalleader()); } }
上面是访问者和被访问者的代码,因为企业是在喜来登酒店宴请*,所以这里还需要一个酒店,酒店里面有企业合作的名单,以及负责宴请各路领导的方法提供。
/** * 酒店 */ 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 等教程
加个人微信备注『教程』获取架构师、机器学习等教程