《设计模式》-- 观察者模式
来源:互联网 发布:卓睿安位软件 编辑:程序博客网 时间:2024/06/14 18:32
观察者模式
参考:《JAVA与模式》之观察者模式
- 观察者模式
- 认识
- 思考
- 使用场景
- 优缺点
- UML图
- 代码实现
- 推模型
- 拉模型
- jdk提供的接口
认识
观察者模式是对象的行为模式,定义了一种一对多的依赖关系,多个观察者对象同时监听一个主题对象,当主题对象状态发生改变时,会通知所有观察者对象更新。是一种发布-订阅模式。
思考
在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖目标,观察者只能被动的去等到目标的通知,等待目标传值给它。
- 推模型是假定目标知道观察者需要的数据;而拉模型是目标不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
- 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是目标对象本身,观察者可以获取目标对象上的任何非私有属性。
实质:触发联动
使用场景
- 当一个对象的改变需要通知其他对象时选用观察者模式
- 当一个抽象模型有两个方面,一个方面的操作依赖另一个方面的状态变化时选用观察者模式
优缺点
优点
- 实现了观察者和目标之间的解耦合
- 支持广播通知
缺点
UML图
定义一个目标抽象类,在抽象类中维护一个观察者的list,通过准备阶段创建观察者add到list中,提供添加和删除观察者的方法,提供通知观察者的方法。
定义一个目标具体实现类,在该实现类中如果发生变化调用notifyObserves通知所有观察者
定义一个观察者接口和一系列观察者实现类对象,提供方法供目标回调
● 目标(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,提供目标更新时通知观察者的方法。
● 目标实现(ConcreteSubject)角色:具体目标实现,用来维护目标状态,当目标状态发生改变时通知已注册的所有观察者。
● 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,定义目标对象通知观察者时的回调方法。
● 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者接收通知进行后续处理。
- 准备阶段
- 运行阶段
代码实现
推模型
目标回调观察者时传入具体的值
//目标抽象类public abstract class Subject { // 注册的观察者列表 private List<Observer> observerList = new ArrayList<Observer>(); // 注册观察者 public void attach(Observer observer) { observerList.add(observer); } // 移除观察者 public void detach(Observer observer) { observerList.remove(observer); } // 定义通知方法 protected void nodifyObservers(String newState) { for(Observer observer:observerList){ observer.update(newState); } }}//目标具体实现类public class ConcreteSubject extends Subject { private String state; public String getState() { return state; } //目标更新时通知所有观察者 public void change(String newState) { state = newState; System.out.println("主题状态为:" + state); // 状态发生改变,通知各个观察者 this.nodifyObservers(state); }}//观察者接口public interface Observer { //提供方法供目标回调通知并传入值 public void update(String state);}//观察者具体实现类public class ConcreteObserver implements Observer { //观察者的状态 private String observerState; //通过目标回调获取目标传递给回来的值 public void update(String state) { /** * 更新观察者的状态,使其与目标的状态保持一致 */ observerState = state; System.out.println("状态为:"+observerState); }}//客户端调用public class Client { public static void main(String[] args) { //创建目标 ConcreteSubject subject = new ConcreteSubject(); //创建观察者 Observer observer1 = new ConcreteObserver(); Observer observer2 = new ConcreteObserver(); //注册观察者 subject.attach(observer1); subject.attach(observer2); //更新目标并通知所有观察者 subject.change("new"); subject.detach(observer2); subject.change("again"); }}
拉模型
目标回调观察者时将目标对象传递给观察者
//目标抽象类public abstract class Subject { // 注册的观察者列表 private List<Observer> observerList = new ArrayList<Observer>(); // 注册观察者 public void attach(Observer observer) { observerList.add(observer); } // 移除观察者 public void detach(Observer observer) { observerList.remove(observer); } // 定义通知方法,直接将目标对象回调传递给观察者 protected void nodifyObservers() { for(Observer observer:observerList){ observer.update(this); } }}//目标具体实现类public class ConcreteSubject extends Subject { private String state; public String getState() { return state; } //目标更新时通知所有观察者 public void change(String newState) { state = newState; System.out.println("主题状态为:" + state); //将目标对象通过回调传递给每个观察者 this.nodifyObservers(); }}//观察者接口public interface Observer { //提供方法供目标回调通知并传入值 public void update(Subject subject);}//观察者具体实现类public class ConcreteObserver implements Observer { //观察者的状态 private String observerState; //通过目标回调获取目标对象 @Override public void update(Subject subject) { //通过目标对象的引用获取目标对象中的值 observerState = ((ConcreteSubject)subject).getState(); System.out.println("状态为:"+observerState); }}//客户端调用public class Client { public static void main(String[] args) { //创建目标 ConcreteSubject subject = new ConcreteSubject(); //创建观察者 Observer observer1 = new ConcreteObserver(); Observer observer2 = new ConcreteObserver(); //注册观察者 subject.attach(observer1); subject.attach(observer2); //更新目标并通知所有观察者 subject.change("new"); subject.detach(observer2); subject.change("again"); }}
jdk提供的接口
//目标对象继承Observable接口public class Watched extends Observable接口{ private String data = ""; public String getData() { return data; } public void setData(String data) { if(!this.data.equals(data)){ this.data = data; setChanged(); } notifyObservers(); }}//观察者实现Observer接口public class Watcher implements Observer{ public Watcher(Observable o){ o.addObserver(this); } @Override public void update(Observable o, Object arg) { System.out.println("状态发生改变:" + ((Watched)o).getData()); }}public class Client { public static void main(String[] args) { //创建被观察者对象 Watched watched = new Watched(); //创建观察者对象,并将被观察者对象登记 Observer watcher = new Watcher(watched); //给被观察者状态赋值 watched.setData("start"); watched.setData("run"); watched.setData("stop"); }}
0 0
- 模式设计:观察者模式
- 设计模式-----观察者模式
- 设计模式-观察者模式
- 设计模式--观察者模式
- 设计模式:观察者模式
- 设计模式-----观察者模式
- 设计模式:观察者模式
- 设计模式-观察者模式
- 设计模式 观察者模式
- 设计模式-观察者模式
- 设计模式-【观察者模式】
- 设计模式-观察者模式
- 设计模式 -- 观察者模式
- 设计模式-观察者模式
- 【设计模式】观察者模式
- 设计模式- 观察者模式
- 设计模式- 观察者模式
- 设计模式--观察者模式
- 我有故事,你有酒吗?(一)
- 数据结构之栈(二):栈的应用——算术表达式
- UML和模式应用学习笔记(9)
- Win64 驱动内核编程-21.DKOM隐藏和保护进程
- 35. Search Insert Position
- 《设计模式》-- 观察者模式
- Apache YARN/Mesos与Google Borg差距多远?
- 在ubuntu中使用virtualenv创建python2和python3的虚拟环境
- Linux Kernel source code of all versions
- Cadence Allegro学习之Add connnect+slide+copy
- Log.v(“ThreeTips”, ”#13”)
- Oracle PL/SQL开发基础(第四弹:索引)
- Spark On Yarn之指定hive-site.xml找不到metastore
- Centos下yum安装LAMP环境