Java设计模式之——观察者模式(Observer)
2017-01-04 13:03
627 查看
年底了,手头上的项目已经处于收尾阶段,没什么新任务。这段时间争取写两三篇关于设计模式的文章,便于自己加深理解。先从观察者模式开始写起。
考虑一种场景,大学校园里,男生们想知道他们女神的动态,但又不可能对女神随时随地尾随不去,穷跟不舍。怎么办,买通她闺蜜(给钱,请吃饭,让她占便宜等等)。女神一有新情况,闺蜜就把相关消息透露给感兴趣的男生。暂定闺蜜只把女神在宿舍的动态往外透露,比如女神回到宿舍了,在洗澡,在和某某男生视频聊天,在看电影等等。
下面用代码实现这种场景,先定义女神的接口:
接着再定义闺蜜的接口,闺蜜需要做两件事,一是收集女神的信息,二是把收集的信息透露给给了自己好处的男生。男生可能会有多个,每个男生都需要通知到,对于男生来说,女神的闺蜜就是他们的观察对象,女神不能直接观察到,只能通过观察她闺蜜,间接观察到女神的动态。这里把闺蜜收集信息和把收集的信息透露给相关男生分成两个接口:
把收集的信息透露给相关男生的接口等一下再定义,先定义男生的接口。相对于女神的闺蜜来说,男生是她的观察者,她是一个被观察者。当闺蜜把消息放出去的时候,接收到消息的男生就会采取相应行动,这里把男生的接口名定为观察者(observer):
接下来再定义女神闺蜜把消息透露给男生的接口,后续可能会有更多男生需要她透露女神的消息,她需要把这些给了好处的男生加入自己的名单中,将消息一一通知给他们,也有些男生不给好处了,她就把他们从
4000
名单中删除,否则自己利益受损。这里将这个接口定义为一个被观察者接口:
接口已经定义好,接下来实现女神一号,女神一号的闺蜜如花,希望得到女神动态的男生一号和男生二号的具体类。首先是女神的具体实现类,女神一号:
接着看闺蜜如花的具体实现类:
接下来看观察者(男生)的两个具体实现类,男生一号和男生二号:
接下来看场景类,把所有这些联系起来:
运行结果如下:
女神一号:回到宿舍了
男生一:好,很好,非常好!
男生二:嗯嗯
女神一号:在洗澡了
男生一:啊!受不了了,老子要打灰机了!
男生二:嘿嘿嘿嘿嘿嘿嘿!
女神一号:在看电影了
男生一:不会是在看精华片吧,嘿嘿!
男生二:看什么电影呢,改天我也看看。
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式提供了一种对象设计,让被观察者(上面例子中的如花)和观察者(上面例子中的男生一号和二号)之间松耦合。
关于观察者的一切,被观察者(如花)只知道观察者(男生)实现了某个接口,被观察者(如花)不需要知道观察者(男生)的具体类是谁、做了什么或其他任何细节。只要男生给如花好处了,不管如花认不认识那个男生,如花都会给他提供女神的相关信息。
任何时候都可以给被观察者(如花)增加新的观察者(男生)。被观察者唯一依赖的东西是一个实现了Observer接口的列表。在运行时可以用新的观察者取代现有的观察者,被观察者不会受到任何影响。也可以在任何时候删除某些观察者。
一、例子
公司开发讨论组,基本上每天斗图,大部分图片让人看着血脉偾张,眼睛离不开,都是漂亮的美女图,是一种不错的休息方式。考虑一种场景,大学校园里,男生们想知道他们女神的动态,但又不可能对女神随时随地尾随不去,穷跟不舍。怎么办,买通她闺蜜(给钱,请吃饭,让她占便宜等等)。女神一有新情况,闺蜜就把相关消息透露给感兴趣的男生。暂定闺蜜只把女神在宿舍的动态往外透露,比如女神回到宿舍了,在洗澡,在和某某男生视频聊天,在看电影等等。
下面用代码实现这种场景,先定义女神的接口:
//女神的接口,定义了三个事件,回到宿舍、洗澡、看电影 public interface IGoddess { //回到宿舍 void backToDormitory(); //洗澡 void haveAShower(); //看电影 void watchMoive(); }
接着再定义闺蜜的接口,闺蜜需要做两件事,一是收集女神的信息,二是把收集的信息透露给给了自己好处的男生。男生可能会有多个,每个男生都需要通知到,对于男生来说,女神的闺蜜就是他们的观察对象,女神不能直接观察到,只能通过观察她闺蜜,间接观察到女神的动态。这里把闺蜜收集信息和把收集的信息透露给相关男生分成两个接口:
//闺蜜的接口一,收集女神信息的接口 public interface IFemaleFriend { //收集女神的信息 void gatherInfo(String content); }
把收集的信息透露给相关男生的接口等一下再定义,先定义男生的接口。相对于女神的闺蜜来说,男生是她的观察者,她是一个被观察者。当闺蜜把消息放出去的时候,接收到消息的男生就会采取相应行动,这里把男生的接口名定为观察者(observer):
//男生的接口,观察者接口 public interface Observer { //收到消息后采取相应行动 void takeAction(String content); }
接下来再定义女神闺蜜把消息透露给男生的接口,后续可能会有更多男生需要她透露女神的消息,她需要把这些给了好处的男生加入自己的名单中,将消息一一通知给他们,也有些男生不给好处了,她就把他们从
4000
名单中删除,否则自己利益受损。这里将这个接口定义为一个被观察者接口:
//闺蜜的接口二,透露消息的接口,被观察者接口 public interface Observable { //给了好处的男生需要加入名单 void addObserver(Observer observer); //不再给好处的男生需要剔除 void deleteObserver(Observer observer); //将消息透露给在名单中的男生 void notifyObservers(String content); }
接口已经定义好,接下来实现女神一号,女神一号的闺蜜如花,希望得到女神动态的男生一号和男生二号的具体类。首先是女神的具体实现类,女神一号:
//女神实现类,名字为女神一号 public class GoddessNumOne implements IGoddess { private IFemaleFriend femaleFriend; public GoddessNumOne(IFemaleFriend femaleFriend){ this.femaleFriend = femaleFriend; } @Override public void backToDormitory() { System.out.println(); System.out.println("女神一号:回到宿舍了"); //身边闺蜜收集信息 femaleFriend.gatherInfo("回到宿舍"); } @Override public void haveAShower() { System.out.println(); System.out.println("女神一号:在洗澡了"); //身边闺蜜收集信息 femaleFriend.gatherInfo("在洗澡"); } @Override public void watchMoive() { System.out.println(); System.out.println("女神一号:在看电影了"); //身边闺蜜收集信息 femaleFriend.gatherInfo("在看电影"); } }
接着看闺蜜如花的具体实现类:
public class RuHua implements Observable, IFemaleFriend{ private ArrayList<Observer> observersList = new ArrayList<>(); @Override public void gatherInfo(String content) { //一收到消息就将消息透露给,给了自己好处的男生 notifyObservers(content); } @Override public void addObserver(Observer observer) { //只要男生给了好处,都加入名单 observersList.add(observer); } @Override public void deleteObserver(Observer observer) { //不给好处就从名单中踢出 observersList.remove(observer); } @Override public void notifyObservers(String content) { //把消息通知给在名单中的男生 for (Observer observer : observersList) { observer.takeAction(content); } } }
接下来看观察者(男生)的两个具体实现类,男生一号和男生二号:
//男生一 public class CollegeBoyOne implements Observer{ @Override public void takeAction(String content) { if (content.equals("回到宿舍")) { System.out.println("男生一:好,很好,非常好!"); } else if (content.equals("在洗澡")) { System.out.println("男生一:啊!受不了了,老子要打灰机了!"); } else if (content.equals("在看电影")) { System.out.println("男生一:不会是在看精华片吧,嘿嘿!"); } } }
//男生二 public class CollegeBoyTwo implements Observer{ @Override public void takeAction(String content) { if (content.equals("回到宿舍")) { System.out.println("男生二:嗯嗯"); } else if (content.equals("在洗澡")) { System.out.println("男生二:嘿嘿嘿嘿嘿嘿嘿!"); } else if (content.equals("在看电影")) { System.out.println("男生二:看什么电影呢,改天我也看看。"); } } }
接下来看场景类,把所有这些联系起来:
public class Client { public static void main(String[] args) { //如花出场 RuHua ruHua = new RuHua(); //男生一出场 Observer collegeBoyOne = new CollegeBoyOne(); //男生二出场 Observer collegeBoyTwo = new CollegeBoyTwo(); //把男生一加入如花的名单 ruHua.addObserver(collegeBoyOne); //把男生二加入如花的名单 ruHua.addObserver(collegeBoyTwo); //女神出场,通过构造器把闺蜜如花传入 IGoddess goddessNumOne = new GoddessNumOne(ruHua); //女神回到宿舍 goddessNumOne.backToDormitory(); //女神在洗澡 goddessNumOne.haveAShower(); //女神在看电影 goddessNumOne.watchMoive(); } }
运行结果如下:
女神一号:回到宿舍了
男生一:好,很好,非常好!
男生二:嗯嗯
女神一号:在洗澡了
男生一:啊!受不了了,老子要打灰机了!
男生二:嘿嘿嘿嘿嘿嘿嘿!
女神一号:在看电影了
男生一:不会是在看精华片吧,嘿嘿!
男生二:看什么电影呢,改天我也看看。
二、观察者模式
上面就是一个观察者模式的例子。观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式提供了一种对象设计,让被观察者(上面例子中的如花)和观察者(上面例子中的男生一号和二号)之间松耦合。
关于观察者的一切,被观察者(如花)只知道观察者(男生)实现了某个接口,被观察者(如花)不需要知道观察者(男生)的具体类是谁、做了什么或其他任何细节。只要男生给如花好处了,不管如花认不认识那个男生,如花都会给他提供女神的相关信息。
任何时候都可以给被观察者(如花)增加新的观察者(男生)。被观察者唯一依赖的东西是一个实现了Observer接口的列表。在运行时可以用新的观察者取代现有的观察者,被观察者不会受到任何影响。也可以在任何时候删除某些观察者。
相关文章推荐
- springmvc无法接收uploadify插件上传的数据
- 论:开发者信仰之“天下IT是一家“(Java .NET篇)
- 2016,Java成神初年
- java性能调优及问题追踪--Btrace的使用
- JAVA设计模式之适配器模式
- javaweb开发过程中小工具系列之支持事务的JdbcUtils
- org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dia
- eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结
- eclipse修改后运行的还是之前的代码
- spring-boot 连接池 druid 的配置及监控
- Java中的instanceof关键字
- java多线程系类:基础篇:08之join
- 利用JDK(1.6及以上版本)创建WebService
- 利用JDK(1.6及以上版本)创建WebService
- java transient简介
- HV000030: No validator could be found for type: java.lang.Integer
- Java中使用Lock控制线程同步
- springboot计划任务(定时任务)
- springboot多线程编程
- spring mvc异常统一处理(使用ControllerAdvice注解)