设计模式之观察者模式
来源:互联网 发布:linux下卸载oracle11g 编辑:程序博客网 时间:2024/05/01 18:52
一堆男生观察美眉的一举一动,一颦一笑
大家学生时代都追过心仪的女生吧,那我们今天从追女生来聊聊观察者模式。
当年我们班的校花叫“晓丽”,那个美啊。对,就是用闭月羞花,沉鱼落雁来形容。我们班的所有男生都想追她(自然包括我),晓丽的一举一动我们都细心的观察,那叫一个美啊,好先说到这,观察晓丽这个动作,用代码实现一下,先看类图:
仅有这二个对象是不够的,我们要解决追求者是怎样监视晓丽的,创建一个后台的线程一直处于运行状态,一旦发现晓丽吃饭或者娱乐就触发事件,那我们就安排一个间谍在晓丽身边(这个间谍就是我买通的晓丽的舍友),观察晓丽的生活起居,并上报给我,然后我就触发update()事件。改一下类图如下:
代码如下:
public interface IXiaoLi { //晓丽吃早饭了 public void haveBreakfast(); //晓丽娱乐了 public void haveFun();}
对接口进行扩充,增加二个状态(是否吃饭和娱乐), 以方便监控:
public class XiaoLi implements IXiaoLi { // 晓丽是否在吃饭,作为监控的判断标准 private boolean isHavingBreakfast = false; // 晓丽是否在娱乐 private boolean isHavingFun = false; // 晓丽要吃饭了 public void haveBreakfast() { System.out.println("晓丽:开始吃饭了...,姿势好美..."); this.isHavingBreakfast = true; } // 晓丽开始娱乐了 public void haveFun() { System.out.println("晓丽:开始娱乐了...,姿势好美..."); this.isHavingFun = true; } // 以下是bean的基本方法,getter/setter,不多说 public boolean isHavingBreakfast() { return isHavingBreakfast; } public void setHavingBreakfast(boolean isHavingBreakfast) { this.isHavingBreakfast = isHavingBreakfast; } public boolean isHavingFun() { return isHavingFun; } public void setHavingFun(boolean isHavingFun) { this.isHavingFun = isHavingFun; }}
下面的抽象的观察者:
public interface ILover{ //一发现别人有动静,自己也要行动起来 public void update(String context);}
观察者的具体实现:
public class Lover implements ILover { // 首先追求者是个观察者,一旦晓丽有活动,他就知道了 public void update(String str) { System.out.println("追求者:"+str+",我好高兴!"); }}
两个重量级的人物都定义出来了,我们的间谍是不是也要登台了:
public class Spy extends Thread { private XiaoLi xiaoLi; private Lover lover; private String type; // 通过构造函数传递参数,我要监控的是谁,谁来监控,要监控什么 public Spy(XiaoLi xiaoLi, Lover lover, String _type) { this.xiaoLi = xiaoLi; this.lover = lover; this.type = _type; } @Override public void run() { while (true) { if (this.type.equals("breakfast")) { // 监控是否在吃早餐 // 如果发现晓丽在吃饭 if (this.xiaoLi.isHavingBreakfast()) { this.lover.update("晓丽在吃饭"); // 重置状态,继续监控 this.xiaoLi.setHavingBreakfast(false); } } else {// 监控是否在娱乐 if (this.xiaoLi.isHavingFun()) { this.lover.update("晓丽在娱乐"); this.xiaoLi.setHavingFun(false); } } } }}
监控程序继承了java.lang.Thread类,可以同时启动多个线程进行监控,Java的多线程机制还是比较简单的,继承Thread类,重写run()方法,然后new SubThread(),再然后 subThread.start()就可以启动一个线程了。我们建立一个场景类来回顾一下这段监控:
public class Client { public static void main(String[] args) throws InterruptedException { // 定义出晓丽和追求者 Lover lover = new Lover(); XiaoLi xiaoLi = new XiaoLi(); // 观察早餐 Spy SpyBreakfast = new Spy(xiaoLi, lover, "breakfast"); // 开始启动线程,监控 SpyBreakfast.start(); // 观察娱乐情况 Spy SpyFun = new Spy(xiaoLi, lover, "fun"); SpyFun.start(); // 然后我们看看晓丽在干什么 Thread.sleep(1000); // 主线程等待1秒后后再往下执行 xiaoLi.haveBreakfast(); // 晓丽娱乐了 Thread.sleep(1000); xiaoLi.haveFun(); } }
运行结果如下:
晓丽:开始吃饭了...,姿势好美...追求者:晓丽在吃饭,我好高兴!晓丽:开始娱乐了...,姿势好美...追求者:晓丽在娱乐,我好高兴!
结果出来,晓丽一吃早饭追求者就知道,晓丽一娱乐追求者也知道,非常正确!
结果正确但并不表示你有成绩,我告诉你:你的成绩是0,甚至是负的!你有没有看到你的CPU飙升,Eclipse直接卡的不动了?反正我的eclipse直接卡的动不了了!!想想这是为什么,看看上面的程序,别的就不多说了,使用了一个死循环while(true)来做监听,要是用到项目中,你要多少硬件投入进来? 你还让不让别人的程序运行了?!一台服务器就跑你这一个程序就完事!
这个程序根本就不是面 向对象的程序,这完全是面向过程的,不改不行,怎么修改呢?我们来想,既然晓丽一吃饭追求者就知道了,那我们为什么不把追求者这个类聚集到晓丽那个类上呢?说改就改,立马动手,我们来看修改后的类图:
晓丽类(被观察者):
public class XiaoLi implements IXiaoLi{ private Lover lover = new Lover(); //晓丽要吃饭了 public void haveBreakfast(){ System.out.println("晓丽:开始吃饭了..."); //通知追求者 this.lover.update("晓丽在吃饭"); } //晓丽开始娱乐了 public void haveFun(){ System.out.println("晓丽:开始娱乐了..."); this.lover.update("晓丽在娱乐"); }}
追求者类就不用再赘述了,运行结果相同,非常简单。
大家再想一想:
晓丽的追求者起至我一个,人数多的都能组成一个连了,那怎么办?
我们在代码中private Lover lover = new Lover();这表明只有我一个人在观察,这是不对的,这么一个大美女怎么可能只有我一个人观察呢?
我们做一下修改:
1. 增加Observable
2. 修改ILover接口名称为Observer
代码如下:
public interface Observable { public void addObserver(Observer observer); public void delObserver(Observer observer); public void notifyObserver(String content);}
被观察者类(晓丽类):
public class XiaoLi implements IXiaoLi,Observable { private ArrayList<Observer> observerList = new ArrayList<Observer>(); // 晓丽要吃饭了 public void haveBreakfast() { System.out.println("晓丽:开始吃饭了..."); this.notifyObserver("晓丽:开始吃饭了...,姿势好美..."); } // 晓丽开始娱乐了 public void haveFun() { System.out.println("晓丽:开始娱乐了..."); this.notifyObserver("晓丽:开始娱乐了...,姿势好美..."); } @Override public void addObserver(Observer observer) { this.observerList.add(observer); } @Override public void delObserver(Observer observer) { this.observerList.remove(observer); } @Override public void notifyObserver(String content) { for (Observer observer : observerList) { observer.update(content); } }}
观察者接口:
public interface Observer { public void update(String context);}
然后三个猥琐的偷窥者(张三,李四,王五):
public class ZhanSanLover implements Observer {
// 首先追求者是个观察者,一旦晓丽有活动,他就知道了
public void update(String str) {
System.out.println(“张三:”+str+”,我好高兴!”);
}
}
public class LiSiLover implements Observer {
// 首先追求者是个观察者,一旦晓丽有活动,他就知道了
public void update(String str) {
System.out.println(“李四:”+str+”,我好高兴!”);
}
}
public class WangWuLover implements Observer {
// 首先追求者是个观察者,一旦晓丽有活动,他就知道了
public void update(String str) {
System.out.println(“王五:”+str+”,我好高兴!”);
}
}
所有的人物都已经登场了,那么我们来看看场景如何演绎:
场景类:
public static void main(String[] args) throws InterruptedException { // 定义出晓丽和追求者 ZhangSanLover zhangSanLover = new ZhangSanLover(); LiSiLover liSiLover = new LiSiLover(); WangWuLover wangWuLover = new WangWuLover(); XiaoLi xiaoLi = new XiaoLi(); xiaoLi.addObserver(zhangSanLover); xiaoLi.addObserver(liSiLover); xiaoLi.addObserver(wangWuLover); xiaoLi.haveBreakfast(); xiaoLi.haveFun();}
运行结果如下:
晓丽:我开始吃饭了…
张三:我看到晓丽开始吃饭了…,姿势好美…,我好高兴!
李四:我看到晓丽开始吃饭了…,姿势好美…,我好高兴!
王五:我看到晓丽开始吃饭了…,姿势好美…,我好高兴!
晓丽:我开始娱乐了…
张三:我看到晓丽开始娱乐了…,姿势好美…,我好高兴!
李四:我看到晓丽开始娱乐了…,姿势好美…,我好高兴!
王五:我看到晓丽开始娱乐了…,姿势好美…,我好高兴!
好了,符合开闭原则,如过再想添加观察者,继承observer类就好了,这就是观察者模式
观察者模式的缺点如下:
1.一个被观察者和多个观察者导致调试非常麻烦
2.java中消息的通知是循序执行,一旦有一个观察者卡壳,会影响整体的执行效率,所以我们建议用异步的方式。
二用java自带的观察者模式
上面的介绍只是让大家知道观察都模式的原理,别光知道用不知道它的原理,其实java早就给我们封装好了,下面我们来看一下:
我们引入下面二个类:
java.util.Observable;
java.util.Observer;
public class XiaoLi extends Observable implements IXiaoLi { // 晓丽要吃饭了 public void haveBreakfast() { System.out.println("晓丽:我开始吃饭了..."); super.setChanged(); super.notifyObservers("我看到晓丽开始吃饭了...,姿势好美..."); } // 晓丽开始娱乐了 public void haveFun() { System.out.println("晓丽:我开始娱乐了..."); super.setChanged(); super.notifyObservers("我看到晓丽开始娱乐了...,姿势好美..."); }}public class ZhangSanLover implements Observer { // 首先追求者是个观察者,一旦晓丽有活动,他就知道了 @Override public void update(Observable o, Object arg) { System.out.println("张三:"+arg.toString()+",我好高兴!"); }}
结尾
好了就讲到这里吧希望对大家有所帮助!
- 设计模式之-观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- Ubuntu sudo的使用
- The Triangle
- js全局变量问题
- 从零开始使用eclipse Ant脚本语言生成.h头文件:[javah] Exception in thread "main" java.lang.NullPointerException
- 汉字转换成拼音
- 设计模式之观察者模式
- TLD for android 移植问题
- 【C++11新特性】 nullptr关键字
- 将js中的object 中的对象遍历出来
- 日志2016-1-7
- UIView的layoutSubviews和drawRect方法何时调用
- [NOI2004]郁闷的出纳员 (Splay)
- sretcarahCgnitaepeRtuohtiWgnirtsbuStsegnoL.3
- eclipse hashmap 发生InvocationException的解决方案