观察者模式
来源:互联网 发布:椭圆曲线密码算法属于 编辑:程序博客网 时间:2024/06/06 20:43
观察者模式是开发中经常用的一个模式。
一、概述
观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
实现观察者模式,我们应该减少针对实现编程,所以建议使用接口实现。
二、观察者模式的角色组成
1. 抽象观察者Observer:为所有的具体观察者定义一个接口,所有潜在的观察者必须实现观察者接口,在得到主题通知时更新自己。
2. 具体观察者ConcreteObserver: 具体观察者可以是任何实现了Observer接口的类。以便使本身的状态与主题的状态协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
3. 可观察者(抽象主题)Subject: 主题接口,即可观察者Observable。把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
4. 具体可观察者(具体主题)ConcreteSubject: 一个具体主题实现了主题接口,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
类图如下:
三、实现观察者模式
1. 抽象主题角色
主题接口规定了具体主题需要实现的添加,删除及通知观察者更新数据的方法
/** * 抽象主题,被观察者 * */public interface Subject { /** * 添加观察者 * * @param observer */ void addObserver(Observer observer); /** * 移除指定的观察者 * * @param observer */ void removeObserver(Observer observer); /** * 移除所有的观察者 */ void removeAll(); /** * data 是要通知给观察者的数据 因为Object是所有类的父类,可以使用多态,当然 你也可以使用 泛型 * * @param data */ void notifyAllObserver(Object data); /** * 单独 通知某一个观察者 * * @param observer * @param data * data 是要通知给观察者的数据 因为Object是所有类的父类,可以使用多态,当然 你也可以使用 泛型 */ void notify(Observer observer, Object data);}2. 抽象观察者角色
观察者接口规定了具体观察者用来更新数据的方法
/** * 抽象观察者接口 */public interface Observer { /** * * @param subject 被观察者 * @param data 被观察者传递给观察者的 数据 */ void update(Subject subject,Object data);}
3. 具体主题角色(被观察者)
public class ConcreteSubject implements Subject{ //观察者集合,用于管理所有的观察者 List<Observer> mList = new ArrayList<>(); @Override public void addObserver(Observer observer) { // TODO Auto-generated method stub // 确保相同的观察者只含有一个 if (observer == null) { throw new NullPointerException("observer == null"); } if (!mList.contains(observer)) { mList.add(observer); } } @Override public void removeObserver(Observer observer) { // TODO Auto-generated method stub mList.remove(observer); } @Override public void removeAll() { // TODO Auto-generated method stub mList.clear(); } @Override public void notifyAllObserver(Object data) { // TODO Auto-generated method stub for (Observer observer : mList) { observer.update(this, data); } } @Override public void notify(Observer observer, Object data) { // TODO Auto-generated method stub if (observer != null) { observer.update(this, data); } }}
4. 具体的观察者角色
可以定义多个具体观察者
观察者One
public class ObserverOne implements Observer { @Override public void update(Subject subject, Object data) { // TODO Auto-generated method stub System.err .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString()); }}观察者Two
public class ObserverTwo implements Observer { @Override public void update(Subject subject, Object data) { // TODO Auto-generated method stub System.err .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString()); }}
观察者Three
public class ObserverThree implements Observer { @Override public void update(Subject subject, Object data) { // TODO Auto-generated method stub System.err .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString()); }}
下面是具体的测试类
public class TestObservePattern {public static void main(String[] args) { // TODO Auto-generated method stub ConcreteSubject concreteSubject = new ConcreteSubject(); ObserverOne observerOne=new ObserverOne(); ObserverTwo observerTwo=new ObserverTwo(); ObserverThree observerThree=new ObserverThree(); concreteSubject.addObserver(observerOne); concreteSubject.addObserver(observerTwo); concreteSubject.addObserver(observerThree); //通知所有的观察者 concreteSubject.notifyAllObserver("wake up,wake up"); //通知某个特定的观察者OberverTwo concreteSubject.notify(observerTwo, "Specila msg for you"); //观察者ObserveThree 决定不再订阅主题 concreteSubject.removeObserver(observerThree); //通知所有的观察者 concreteSubject.notifyAllObserver("new Message come "); }}运行截图
通过日志可以看到:
主题内容更新后,所有的观察者将接收到更新结果。
某个特定的观察者取消对主题的订阅后,自身不再接收到主题的更新,而且也不影响主题的实现
四、小结
观察者模式使用场景
1. 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
2. 事件多级触发场景。
3. 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
PS: 文中的实例代码 摘录自观察者模式。
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- Oracle数据库-2
- 执行mvn 报错 source-1.5 中不支持 diamond运算符
- ssh 远程执行命令操作
- SWUST 2489 上决欺负HZF
- ListView中Item的子控件与Item点击事件冲的解决方式
- 观察者模式
- 浏览器总提示本地没有安装jre
- 论helloworld114(IT行业垂直导航)站点的存在价值
- C/C++中extern关键字详解(转)
- js 文本编辑器
- oracle基本命令
- 欢迎使用CSDN-markdown编辑器
- NavigationBar 隐藏和显示带来的问题和解决办法
- 【oracle】DECODE ,NVL,NVL2的用法