在上一篇中咱们学习了行为型模式的解释器模式(Interpreter Pattern)和迭代器模式(Iterator Pattern)。本篇则来学习下行为型模式的两个模式,访问者模式(Visitor Pattern)和中介者模式(Mediator Pattern)。html
简介java
访问者模式(VisitorPattern),顾名思义使用了这个模式后就能够在不修改已有程序结构的前提下,经过添加额外的访问者来完成对已有代码功能的提高,它属于行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操做。一旦这些操做须要修改的话,接受这个操做的数据结构则能够保持不变。
其主要目的是将数据结构与数据操做分离。git
访问者模式能够说是设计模式中最难以理解的一个模式,由于相比其它模式而言,它过于”绕“了。可是咱们能够经过生活中的一些例子来理解它,好比家里来了客人,客人就是访问者,他能够作一些事情,可是又不能作所有的事情; 又或者说去网吧上网的小明,小明也是访问者,他能够在网吧玩游戏、看视频、听音乐等等,可是不能破坏网吧中的设备等等。按照这么理解,咱们大概就能够知道访问者模式主要是作什么了。github
访问者模式主要由这五个角色组成,抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象节点(Node)、具体节点(ConcreteNode)和结构对象(ObjectStructure)。设计模式
示例图以下:
微信
这里为了方便理解,咱们使用一个简单的示例来加以说明。
图书馆有一台电脑,有两个帐户,其中一个是管理员的帐户,拥有全部权限,可是设置了密码;另外一个帐户是不须要密码,可是只能玩游戏和看图片。张三和李四前后使用了这台电脑,那么他们就能够看成是访问者。
那么咱们即可以根据这里例子来使用访问者模式进行开发,首先定义一个抽象的访问者,拥有玩游戏和看图片的方法;而后再定义一个抽象节点电脑,接受这个请求。
那么这个抽象类的代码以下:数据结构
interface Visitor { void visit(Games games); void visit(Photos photos); } interface Computer { void accept(Visitor visitor); }
定义好该抽象类以后,咱们须要设计不一样的访问者对节点进行不一样的处理。而且须要设计具体节点类实现刚刚抽象节点的方法。ide
那么代码以下:学习
class ZhangSan implements Visitor { @Override public void visit(Games games) { games.play(); } @Override public void visit(Photos photos) { photos.watch(); } } class LiSi implements Visitor { @Override public void visit(Games games) { games.play(); } @Override public void visit(Photos photos) { photos.watch(); } } class Games implements Computer { @Override public void accept(Visitor visitor) { visitor.visit(this); } public void play() { System.out.println("play lol"); } } class Photos implements Computer { @Override public void accept(Visitor visitor) { visitor.visit(this); } public void watch() { System.out.println("watch scenery photo"); } }
最后咱们还须要定义一个结构对象角色,提供一个的接口并容许该访问者进行访问,它能够对这些角色进行增长、修改或删除等操做和遍历。
代码以下:测试
class ObjectStructure { private List<Computer> computers = new ArrayList<Computer>(); public void action(Visitor visitor) { computers.forEach(c -> { c.accept(visitor); }); } public void add(Computer computer) { computers.add(computer); } }
编写好以后,那么咱们来进行测试。
测试代码以下:
public static void main(String[] args) { // 建立一个结构对象 ObjectStructure os = new ObjectStructure(); // 给结构增长一个节点 os.add(new Games()); // 给结构增长一个节点 os.add(new Photos()); // 建立一个访问者 Visitor visitor = new ZhangSan(); os.action(visitor); }
输出结果:
play lol watch scenery photo
访问者模式优势:
扩展性好,能够在不修改对象结构中的元素的状况下,为对象结构中的元素添加新的功能;
符合单一职责原则,经过访问者将无关的行为分离,使职责单一;
访问者模式缺点:
违反了迪米特原则,由于具体元素对访问者公布细节;
违反了依赖倒置原则,依赖了具体类,没有依赖抽象;
对象结构变化困难,若对象结构发生了改变,访问者的接口和访问者的实现也都要发生相应的改变;
使用场景:
对象结构中对象对应的类不多改变,但常常须要在此对象结构上定义新的操做;
须要对一个对象结构中的对象进行不少不一样的而且不相关的操做,而须要避免让这些操做"污染"这些对象的类,也不但愿在增长新操做时修改这些类。
简介
中介者模式(Mediator Pattern),定义了一个中介对象来封装一系列对象之间的交互关系。中介者使各个对象之间不须要显式地相互引用,从而使耦合性下降,并且能够独立地改变它们之间的交互行为,属于行为型模式。
其主要的目的是用来下降多个对象和类之间的通讯复杂性。
简单的来讲就是提供一个平台。好比生活中咱们常常用到的聊天软件QQ、微信群,或者是上网购物的网站淘宝、京东,又或者是房产中介。可是不管是QQ群,仍是房产中介,他们都是充当一个中间平台的做用,咱们能够直接经过这个平台获得咱们想要的信息,避免了独自获取花费的成本。
中介者模式主要由这四个角色组成, 抽象中介者(Mediator)、具体中介者(ConcreteMediator)、 抽象同事类(Colleague)和具体同事类(ConcreteColleague) 。
示例图以下:
这里为了方便理解,咱们使用一个简单的示例来加以说明。
xuwujing建立了一个Java的QQ群,并邀请了不少人进来,其中张三也加进来了,进群以后,你们开始互相打招呼进行交流。。。
那么咱们即可以根据这个简单的例子来使用中介者模式进行开发。
首先依旧定义一个抽象的中介者,就是QQ群,能够进行交流;而后再定义一个抽象的同事类,能够谈话。
那么这个抽象类的代码以下:
interface QQqun { void exchange(Person person,String message); } abstract class Person{ protected String name; protected QQqun qun; Person(String name,QQqun qun){ this.name = name; this.qun = qun; } }
定义好该抽象类以后,咱们再来定义具体的同事类,也就是xuwujing和张三,能够进行交流。
那么代码以下:
class ZhangSan extends Person{ ZhangSan(String name, QQqun qun) { super(name, qun); } void exchange(String message){ qun.exchange(this,message); } void talk(String message){ System.out.println(name +"说:" + message); } } class XuWuJing extends Person{ XuWuJing(String name, QQqun qun) { super(name, qun); } void exchange(String message){ qun.exchange(this,message); } void talk(String message){ System.out.println(name +"回应:" + message); } }
最后再来定义具体中介者对象,这个QQ群的具体实现。
代码以下:
class JavaQQqun implements QQqun{ private ZhangSan zs; private XuWuJing xwj; public ZhangSan getZs() { return zs; } public void setZs(ZhangSan zs) { this.zs = zs; } public XuWuJing getXwj() { return xwj; } public void setXwj(XuWuJing xwj) { this.xwj = xwj; } @Override public void exchange(Person person, String message) { if(zs.equals(person)){ zs.talk(message); }else if(xwj.equals(person)){ xwj.talk(message); } } }
最后再来进行测试,定义好交流平台以及须要交流的人员。
那么测试代码以下:
public static void main(String[] args) { JavaQQqun jq = new JavaQQqun(); ZhangSan zs = new ZhangSan("张三", jq); XuWuJing xwj = new XuWuJing("xuwujing", jq); jq.setZs(zs); jq.setXwj(xwj); zs.exchange("你们好!我是张三!"); xwj.exchange("欢迎你!张三!"); }
输出结果:
张三说:你们好!我是张三 xuwujing回应:欢迎你!张三!
中介者模式优势:
灵活性高,由于将同事类进行了解耦,使其没必要有关联性;
下降了类的复杂度,将一对多转化成了一对一;
中介者模式缺点:
中介者使用过多,会使系统变得复杂难以维护;
使用场景:
经过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
注意事项:
若不明确各个类的职责,那么就不要进行使用!
和外观模式、代理模式比较
中介者模式和外观模式、代理模式比较相似,可是又有不一样。
和外观模式比较,中介者模式中,同事类必须依赖与中介者,中介者也知道同事类;可是外观模式中,子系统是不须要知道外观类的存在,而且子系统是能够脱离外观模式的。
和代理模式,代理模式的核心就是代理做用,主要仍是对原先的类进行扩展或增长控制,好比进行权限控制;而中介者模式主要目的是为了减小对象以前的耦合,也就是同事类直接相互独立,互不影响。
参考文章: https://www.cnblogs.com/chenssy/p/3348520.html
分享一首颇有节奏感的电音!
java-study是本人在学习Java过程当中记录的一些代码,也包括以前博文中使用的代码。若是感受不错,但愿顺手给个start,固然若是有不足,也但愿提出。
github地址: https://github.com/xuwujing/java-study
原创不易,若是感受不错,但愿给个推荐!您的支持是我写做的最大动力! 版权声明: 做者:虚无境 博客园出处:http://www.cnblogs.com/xuwujing CSDN出处:http://blog.csdn.net/qazwsxpcm 我的博客出处:http://www.panchengming.com