观察者模式 : 一支穿云箭,千军万马来相见
来源:互联网 发布:删除语句sql 编辑:程序博客网 时间:2024/05/22 07:59
小时候一块钱就可以在录像厅看一天电影,印象里最喜欢星爷的电影,特别搞笑。
后来渐渐长大,接触了一些人和事,略微懂了他的那些苦笑、狂笑和欲哭无泪。
我喜欢的演员很多,唯独星爷,能让我看到他的照片,有种想哭的感觉。
星爷,may the god bless you.
最近又看了遍《功夫》,其中有一幕:
阿星装比失败,不曾想引来了斧头帮,斧头帮老大一支穿云箭,真的是千军万马来相见,帅呆了!
骨子里也是个古惑仔的我好崇拜这种场景!太帅了!那,这是怎么做到的呢?
- 首先我得加入斧头帮,成为斧头帮一份子
- 然后去登记,有啥事方便通知
- 等老大一发穿云箭
- 我跟其他小弟就赶紧出现
用代码实现一下:
1.首先定义 斧头帮老大 AxeGangBoss:
/** * description: 斧头帮老大,消息发布者,继承 Observable * <br/> * author: shixinzhang * <br/> * data: 9/20/2016 */public class AxeGangBoss extends Observable { private String mName; public AxeGangBoss(String name) { mName = name; } /** * 在需要通知小弟的时候调用 setChanged()方法,表明有更新 * 然后提醒所有小弟 * @param msg */ public void sendMsg(String msg) { //表示有更新 setChanged(); notifyObservers(msg); } public String getName() { return mName; } public void setName(String name) { mName = name; }}
斧头帮老大是消息发布者,当有情况时就调用 sendMsg(…) 方法给小弟发消息。他继承自 Java 源代码提供的 Observable :
public class Observable { List<Observer> observers = new ArrayList<Observer>(); boolean changed = false; public Observable() { } public void addObserver(Observer observer) { if (observer == null) { throw new NullPointerException("observer == null"); } synchronized (this) { if (!observers.contains(observer)) observers.add(observer); } } protected void clearChanged() { changed = false; } public int countObservers() { return observers.size(); } public synchronized void deleteObserver(Observer observer) { observers.remove(observer); } public synchronized void deleteObservers() { observers.clear(); } public boolean hasChanged() { return changed; } public void notifyObservers() { notifyObservers(null); } @SuppressWarnings("unchecked") public void notifyObservers(Object data) { int size = 0; Observer[] arrays = null; synchronized (this) { if (hasChanged()) { clearChanged(); size = observers.size(); arrays = new Observer[size]; observers.toArray(arrays); } } if (arrays != null) { for (Observer observer : arrays) { observer.update(this, data); } } } protected void setChanged() { changed = true; }}
Observable 里保存着一个 Observer 的集合,然后提供了添加、删除、提醒等方法。其中重要的是 notifyObservers(…) 方法,当确定出事了(changed 为 true)时 ,挨个通知小弟。
Observer 是一个接口,规定了小弟收到消息的方法 update(…):
public interface Observer { void update(Observable observable, Object data);}
2.定义斧头帮小弟 AxeGangPeople,小弟需要按规矩来,实现 Observer 接口:
/** * description: 斧头帮小弟,订阅者,实现 Observer 接口 * <br/> * author: shixinzhang * <br/> * data: 9/20/2016 */public class AxeGangPeople implements Observer { String mName; public AxeGangPeople(String name){ mName = name; } /** * 必须实现的方法,当消息发布者发出通知后,会调用这个方法 * @param observable * @param data */ @Override public void update(Observable observable, Object data) { AxeGangBoss writer; if (observable instanceof AxeGangBoss) { writer = (AxeGangBoss) observable; System.out.println(getName() + " 收到来自 " + writer.getName() + " 的消息: " + data.toString()); } } public String getName() { return mName; } public void setName(String name) { mName = name; }}
3.然后小弟去老大那登记,老大有消息了就射穿云箭:
@Test public void testSendMsg() throws Exception { //创建一个斧头帮老大 AxeGangBoss shixinzhang = new AxeGangBoss("张拭心"); //创建两个小弟 AxeGangPeople niefeng = new AxeGangPeople("聂风"); AxeGangPeople bujingyun = new AxeGangPeople("步惊云"); //老大觉得可以,收入麾下 shixinzhang.addObserver(niefeng); shixinzhang.addObserver(bujingyun); //老大出事了,赶紧射箭! shixinzhang.sendMsg("我有难了,快来救我!"); }
4.运行结果:
这种 一对多的通知场景 就是传说中的观察者模式。
观察者模式
1.定义:
又称“发布-订阅模式”,定义了一种一对多的依赖关系,一个被观察者持有多个观察者对象的引用,当被观察者状态发生改变时,通知所有观察者进行更新。
2.UML 图
其中 Subject 是被观察者接口,即上文提到的 Observable ,持有一个观察者接口集合的引用,定义了观察者的添加、删除以及提醒;
ConcreteSubject 实现了被观察者接口,即上文的斧头帮老大 AxeGangBoss,在一定情况下提醒观察者更新;
- Observer 是观察者抽象类,定义了更新 update 方法;
- ConcreteObserver 是具体观察者,即上文的小弟 AxeGangPeople,重写 update 方法,进行触发操作。里面有时需要持有一个 Subject 的引用。
3.场景:
有的时候一个状态值会影响许多逻辑,比如电商类软件的位置信息,如果用户切换位置,需要显示对应城市的商品信息、活动、附件的人等等,这时使用观察者模式可以减少对应模块的代码逻辑,直接写好回调方法,等待被回调就好,耦合度降低很多。
4.备注
代码地址点这里
下一篇博客我们通过查看 ListView 源码中的观察者模式 来加深理解。
- 观察者模式 : 一支穿云箭,千军万马来相见
- 观察者模式 : 一支穿云箭,千军万马来相见
- 第十三篇:观察者模式 : 一支穿云箭,千军万马来相见
- 快递江湖:一支穿云箭 千军万马来相见
- 一枝穿云箭,千军万马来相见——致2015届电子科大信软学院新生
- 来聊聊观察者模式
- 老师来了——观察者模式
- 设计模式-观察者模式,以及如何使用观察者来为app实现即时通讯功能
- 如何使用委托与事件来实现观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- Ubuntu复制指定目录下的全部文件到另一个目录中
- java基础知识(个人笔记)
- FFmpeg常用推流命令
- 在SQL SERVER中当查询的条件是一个选择范围的SQL语句怎么写?
- Codeforces 429B Working out (动态规划) -- 解题报告
- 观察者模式 : 一支穿云箭,千军万马来相见
- Java TCP/IP
- 剑指offer--面试题37:两个链表的第一个公共结点
- JZOJ2904 【集训队互测 2012】Calc 用倍增的思路转移dp
- HDU 1257 最少拦截系统 DP -
- Qt5的下载和安装
- 自己编译openwrt 8m固件 简单记录
- HBase 分区Region自动转移测试
- Git fetch和Git pull的区别