一、观察者模式定义

观察者模式定义:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents aer notified and updated automatically.
定义对象间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

  如上图所示(截取自《Head First Design Patterns》一书),主要包括四个部分:

  1. Subject被观察者。是一个接口或者是抽象类,定义被观察者必须实现的职责,它必须能偶动态地增加、取消观察者,管理观察者并通知观察者。

  2. Observer观察者。观察者接收到消息后,即进行update更新操作,对接收到的信息进行处理。

  3. ConcreteSubject具体的被观察者。定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。

  4. ConcreteObserver具体观察者。每个观察者在接收到信息后处理的方式不同,各个观察者有自己的处理逻辑。

二、观察者模式优势

观察者和被观察者之间是抽象耦合的,不管是增加观察者还是被观察者都非常容易扩展。

根据单一职责原则,每个类的职责是单一的,那么怎么把各个单一的职责串联成真实的复杂的逻辑关系呢,观察者模式可以起到桥梁作用。
观察者模式是松耦合的典型。

  在Android源码中,其中一个经典的使用到观察者模式的就是Android控件的事件监听模型。

三、观察者模式的实例

1、定义一个抽象被观察者接口

package com.linghu.observer;

/***
* 抽象被观察者接口
* 声明了添加、删除、通知观察者方法
* @author linghu
*
*/
public interface Observerable { public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver(); }

2、定义一个抽象观察者接口

package com.linghu.observer;

/***
* 抽象观察者
* 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。
* @author linghu
*
*/
public interface Observer {
public void update(String message);
}

3、定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。

package com.linghu.observer;

import java.util.ArrayList;
import java.util.List; /**
* 被观察者,也就是微信公众号服务
* 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现
* @author linghu
*
*/
public class WechatServer implements Observerable { //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
private List<Observer> list;
private String message; public WechatServer() {
list = new ArrayList<Observer>();
} @Override
public void registerObserver(Observer o) {
list.add(o);
} @Override
public void removeObserver(Observer o) {
if(!list.isEmpty())
list.remove(o);
} //遍历
@Override
public void notifyObserver() {
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
} public void setInfomation(String s) {
this.message = s;
System.out.println("微信服务更新消息: " + s);
//消息更新,通知所有观察者
notifyObserver();
} }

4、定义具体观察者,微信公众号的具体观察者为用户User

package com.linghu.observer;

/**
* 观察者
* 实现了update方法
* @author linghu
*
*/
public class User implements Observer {
private String name;
private String message; public User(String name) {
this.name = name;
} @Override
public void update(String message) {
this.message = message;
read();
} public void read() {
System.out.println(name + " 收到推送消息: " + message);
} }

5、编写一个测试类

首先注册了三个用户,ZhangSan、LiSi、WangWu。公众号发布了一条消息"PHP是世界上最好用的语言!",三个用户都收到了消息。

用户ZhangSan看到消息后颇为震惊,果断取消订阅,这时公众号又推送了一条消息,此时用户ZhangSan已经收不到消息,其他用户

还是正常能收到推送消息。

package com.linghu.observer;

public class Test {

    public static void main(String[] args) {
WechatServer server = new WechatServer(); Observer userZhang = new User("ZhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu"); server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的语言!"); System.out.println("----------------------------------------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的语言!");
}
}

四、观察者模式在Android源码中的应用

  1. 看View类源代码中的OnKeyListener接口:

    /**
* Interface definition for a callback to be invoked when a key event is
* dispatched to this view. The callback will be invoked before the key
* event is given to the view.
*/
public interface OnKeyListener {
/**
* Called when a key is dispatched to a view. This allows listeners to
* get a chance to respond before the target view.
*
* @param v The view the key has been dispatched to.
* @param keyCode The code for the physical key that was pressed
* @param event The KeyEvent object containing full information about
* the event.
* @return True if the listener has consumed the event, false otherwise.
*/
boolean onKey(View v, int keyCode, KeyEvent event);
}

  2. 再看View类定义了私有成员mOnKeyListener(通过组合的方式):

private OnKeyListener mOnKeyListener;

  3. 注册listener

    /**
* Register a callback to be invoked when a key is pressed in this view.
* @param l the key listener to attach to this view
*/
public void setOnKeyListener(OnKeyListener l) {
mOnKeyListener = l;
}

  4. 剩下的就交给开发者自己构造外部观察者对象与该按键的事件接口进行绑定,获取事件消息。

  最后让我们记住支撑“观察者模式”的设计原则: Strive for loosely coupled designs between objects that interact.

最新文章

  1. RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密
  2. 关于如何在Android、Java等非微软平台上建立高信任的SharePoint应用程序
  3. GPS部标平台的架构设计(四)-百度地图设计
  4. /usr/include/sys/types.h:62: error: conflicting types for ‘dev_t’
  5. Js:DOM对象操作常用的方法和属性
  6. PowerCMD——cmd的命令行工具
  7. QRadioButton 使用方法
  8. Html5工具
  9. js获取iframe的parent对象
  10. fedora之防火墙
  11. Spring Framework 5.0.0.M3中文文档 翻译记录 Part I. Spring框架概览2.3
  12. Web 应用性能和压力测试工具 Gor - 运维生存时间
  13. 总结配置搭建tomcat时碰到的一些小问题
  14. java基础程序题
  15. WebAPI问题追踪日志记录过滤器
  16. Collections与Collection
  17. 【AtCoder】ARC097 (C - F)题解
  18. A5-1和DES两个加密算法的学习
  19. S 导入公司数据
  20. js 弹出层,以及在javascript里定义层样式

热门文章

  1. HBase快速上手
  2. android在linux下刷机
  3. mysql 挑选列导入
  4. Linux 硬盘工具之hdparm
  5. nexus3 搭建maven远程仓库
  6. No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer解决方法
  7. ModleAndView类是干什么的???
  8. 微信小程序(一)基本知识初识别
  9. 66. Plus One 数组加1
  10. 获取网页上的所有QQ号码,并生成exel报表