深入浅出设计模式——从球赛中悟观察者模式
2017-08-08 13:31
711 查看
摘要: 观察者模式,主要用来处理对象的一对多的关系,一个主题(Subject),多个观察者(Observer),当主题发生变化时观察者会及时得到通知。
就好比在足球比赛中,教练员会在场边发布命令,然后场上所有的队员都要根据它的命令作出响应,这时,场上的队员就是观察者,教练发出的口令就是主题。
从上面的UML图中我们可以看出观察者模式由两个部分组成:
1. 主题(Subject):也叫被观察者,如果主题发生改变那么观察者会接到通知
2. 观察者(Observer)
接口中包含3个方法,注册观察者,删除观察者,和通知。这里对最基础的观察者模式做了一个小的拓展,那就是观察者可以自行注册和删除,当且仅当观察者在这个主题里注册了才会收到通知。
(1)注册观察者:观察者如需订阅这个主题那么就调用注册方法,下一次主题改变时就会收到通知。
(2)删除观察者:观察者如果不想再收到这个主题的通知则调用这个方法,以后主题再改变时也不会收到通知。
(3)通知:主题发生改变时,调用这个方法通知已注册的观察者。
观察者接口只需要一个update方法用于接受通知并做相应的处理。
主题实现类包含了所有观察者所需要的所有信息,并且在信息发生改变时(setStrategy)调用notifyObservers()方法向观察者发送通知。notifyObservers()实现的方法就是调用observers列表中的每一个观察者的update()方法。
第二个观察者:后卫
主题类将所有的信息都交给观察者,而观察者从里面取出自己需要的信息进行处理就可以了。
执行main方法得到结果:
可以看出主题每一次变化订阅了主题的观察者都能收到相应的通知,然后他们从里面提取自己需要的信息进行处理。这就是观察者模式。
2. 有一套触发机制
2. 观察者只知道主题变化的结果而不知道主题是怎么变化的。
世界上没有十全十美的模式,每个设计模式都有它适用的地方,只要我们的使用方式得当,那么观察者模式可以帮助我们写出漂亮优雅的代码。
附源码地址:http://git.oschina.net/jack90john/observer
------------------------------------------------------------------------------
欢迎关注我的个人公众号,推送最新文章
一、观察者模式概念
观察者模式是指在对象之间定义一对多的依赖,当一个对象改变状态时,依赖它的对象都会收到通知并自动更新。就好比在足球比赛中,教练员会在场边发布命令,然后场上所有的队员都要根据它的命令作出响应,这时,场上的队员就是观察者,教练发出的口令就是主题。
二、使用场景
在一个对象有改变其他依赖对象需要接到通知时三、结构
从上面的UML图中我们可以看出观察者模式由两个部分组成:
1. 主题(Subject):也叫被观察者,如果主题发生改变那么观察者会接到通知
2. 观察者(Observer)
四、实现
在Java中可以通过继承JDK中的Observable类和实现Observer接口来实现观察者模式,但是不提倡这样做,因为Java是单继承语言,如果主题类需要用到观察者模式但同时它又继承了其他类,这样的情况就很尴尬。所以建议自己写主题类,况且这也不难实现。下面我们就从头开始自己实现观察者模式。1. 定义主题接口
import observer.Observer; /** * Description: 主题 * Designer: jack * Date: 2017/8/7 * Version: 1.0.0 */ public interface Subject<T extends Subject> { void registerObserver(Observer<T> observer); // 注册观察者 void removeObserver(Observer observer); //删除观察者 void notifyObservers(); //当主题改变时,调用这个方法通知所有观察者 }
接口中包含3个方法,注册观察者,删除观察者,和通知。这里对最基础的观察者模式做了一个小的拓展,那就是观察者可以自行注册和删除,当且仅当观察者在这个主题里注册了才会收到通知。
(1)注册观察者:观察者如需订阅这个主题那么就调用注册方法,下一次主题改变时就会收到通知。
(2)删除观察者:观察者如果不想再收到这个主题的通知则调用这个方法,以后主题再改变时也不会收到通知。
(3)通知:主题发生改变时,调用这个方法通知已注册的观察者。
2. 观察者接口
import subject.Subject; /** * Description: 观察者接口 * Designer: jack * Date: 2017/8/7 * Version: 1.0.0 */ public interface Observer<T extends Subject> { void update(T t); //当需要改变战术时将新的战术通知给对应当球员 }
观察者接口只需要一个update方法用于接受通知并做相应的处理。
3. 主题实现类
package subject; import observer.Observer; import java.util.ArrayList; import java.util.stream.Collectors; /** * Description: 球员战术指示 * Designer: jack * Date: 2017/8/7 * Version: 1.0.0 */ public class PositionAndStrategy implements Subject<PositionAndStrategy>{ private ArrayList<Observer<PositionAndStrategy>> observers; //观察者注册信息列表 private String strikerStrategy; //前锋战术指令 private String defenderStrategy; //后卫战术指令 public PositionAndStrategy() { this.observers = new ArrayList<>(); } @Override public void registerObserver(Observer<PositionAndStrategy> observer) { this.observers.add(observer); } @Override public void removeObserver(Observer observer) { this.observers = this.observers.stream() .filter(observer1 -> !observer1.equals(observer)) .collect(Collectors.toCollection(ArrayList::new)); } @Override public void notifyObservers() { this.observers.forEach(observer -> observer.update(this)); } public void setStrategy(String strikerStrategy, String defenderStrategy) { this.strikerStrategy = strikerStrategy; this.defenderStrategy = defenderStrategy; notifyObservers(); } public String getStrikerStrategy() { return strikerStrategy; } public String getDefenderStrategy() { return defenderStrategy; } }
主题实现类包含了所有观察者所需要的所有信息,并且在信息发生改变时(setStrategy)调用notifyObservers()方法向观察者发送通知。notifyObservers()实现的方法就是调用observers列表中的每一个观察者的update()方法。
4. 观察者实现
第一个观察者:前锋import subject.PositionAndStrategy; /** * Description: 前锋 * Designer: jack * Date: 2017/8/7 * Version: 1.0.0 */ public class Striker implements Observer<PositionAndStrategy>{ @Override public void update(PositionAndStrategy positionAndStrategy) { //他只需要执行前锋的战术就好了,不用管后卫是什么战术 System.out.println("前锋:" + positionAndStrategy.getStrikerStrategy() ); } }
第二个观察者:后卫
import subject.PositionAndStrategy; /** * Description: * Designer: jack * Date: 2017/8/7 * Version: 1.0.0 */ public class Defender implements Observer<PositionAndStrategy>{ @Override public void update(PositionAndStrategy positionAndStrategy) { System.out.println("后卫:" + positionAndStrategy.getDefenderStrategy() ); } }
主题类将所有的信息都交给观察者,而观察者从里面取出自己需要的信息进行处理就可以了。
5. 实现类
import observer.Defender; import observer.Striker; import subject.PositionAndStrategy; public class Main { public static void main(String[] args) { //创建战术板(主题类) PositionAndStrategy positionAndStrategy = new PositionAndStrategy(); //创建前锋和后卫(观察者) Striker striker = new Striker(); Defender defender = new Defender(); //在主题中注册观察者 positionAndStrategy.registerObserver(striker); positionAndStrategy.registerObserver(defender); //主题发生变化 System.out.println("主题第一次变化!"); positionAndStrategy.setStrategy("进攻", "防守"); //现在后卫距离太远,听不到教练的指令了(删除观察者) positionAndStrategy.removeObserver(defender); //主题发生变化 System.out.println("\n主题第二次变化"); positionAndStrategy.setStrategy("继续进攻", "压上支援"); //后卫现在又能听到指令了 positionAndStrategy.registerObserver(defender); //主题发生变化 System.out.println("\n主题第三次变化"); positionAndStrategy.setStrategy("表现的不错,保持住", "后卫你们在干什么,叫你们压上支援"); } }
执行main方法得到结果:
可以看出主题每一次变化订阅了主题的观察者都能收到相应的通知,然后他们从里面提取自己需要的信息进行处理。这就是观察者模式。
五、优点
1. 观察者与被观察者之间的耦合度低2. 有一套触发机制
六、局限性
1. 如果一个主题中观察者过多会导致效率降低。2. 观察者只知道主题变化的结果而不知道主题是怎么变化的。
世界上没有十全十美的模式,每个设计模式都有它适用的地方,只要我们的使用方式得当,那么观察者模式可以帮助我们写出漂亮优雅的代码。
附源码地址:http://git.oschina.net/jack90john/observer
------------------------------------------------------------------------------
欢迎关注我的个人公众号,推送最新文章
相关文章推荐
- 深入浅出设计模式——从球赛中悟单例模式
- 【C++深入浅出】设计模式学习之观察者模式
- 201802272130->深入浅出设计模式:c#观察者模式
- 深入浅出设计模式之观察者模式
- 深入浅出设计模式python版——观察者模式(observer)
- 深入浅出设计模式——从球赛中悟命令模式
- 设计模式 深入浅出之——观察者模式
- 深入浅出设计模式——从球赛中悟命令模式
- 深入浅出设计模式之策略模式、观察者模式
- 深入浅出设计模式笔记之十六:观察者模式
- 深入浅出设计模式——从球赛中悟多例模式
- 深入浅出设计模式之观察者设计模式
- 深入浅出设计模式——从球赛中悟装饰者模式
- 深入浅出设计模式-002:观察者模式(Observer Pattern)
- 深入浅出设计模式——观察者模式(Observer Pattern)
- 设计模式之 - 观察者模式
- Python设计模式——观察者模式
- 设计模式-Observer(观察者模式)
- 设计模式之观察者模式
- android设计模式之--观察者模式