Java设计模式(6)之观察者模式学习总结
2017-10-28 11:20
681 查看
观察者模式:在观察者模式中,存在着对象之间的一对多的依赖关系,即一个对象的状态发生改变时,所有依赖于该对象的对象都会得到通知,并对自身的状态进行更新; 观察者模式的学习中,对象之间的一对多的依赖关系是学习观察者模式的切入点,而被依赖对象(目标对象)的状态改变会对依赖对象(观察者对象)状态产生影响是观察者模式的关键所在;只有对象之间形成一对多的依赖关系,才能实现被依赖对象与依赖对象之间的状态更新的交互作用; 生活中,其实存在很多观察者模式的应用场景,比如天气预报短信通知,当你在手机上开通了短信通知天气服务之后,每天你都会收到当天的天气信息的短信通知;再比如,你的手机上安装了腾讯体育APP,那么你只要接受该APP提供的推送即时消息通知的服务,那么一旦有更新的体育信息,将会向你的手机推送相关信息; 下面通过一个生活中的场景,进行相关的观察者模式设计代码:
package com.pattern.observer; import java.util.ArrayList; import java.util.List; /** * 抽象目标类 * @author Administrator */ public class Subject { //订阅者列表,用于存放订阅者对象 private List<Observer> list = new ArrayList<Observer>(); //添加订阅者 public void add(Observer o) { list.add(o); } //删除指定订阅者 public void delete(Observer o) { list.remove(o); } //通知所有订阅者 public void notifyAllObservers() { for (Observer observer : list) { //将目标对象传入观察者对象的update方法 observer.update(this); } } } package com.pattern.observer; /** * 具体目标类 * @author Administrator */ public class WeatherSubject extends Subject { //目标对象的状态信息 private String information; public String getInformation() { return information; } //设置或更新目标状态信息 public void setInformation(String information) { this.information = information; //更新状态信息后,调用通知方法,通知所有订阅者,使其进行各自的状态更新 this.notifyAllObservers(); } } package com.pattern.observer; /** * 观察者接口 * @author Administrator */ public interface Observer { //更新观察者状态 public abstract void update(Subject subject); } package com.pattern.observer; /** * 具体观察者类 * @author Administrator */ public class ConcreteObserver implements Observer { //观察者的名字 private String observerName; //观察者的待更新状态信息 private String information; //接收到信息后的响应信息 private String hint; public ConcreteObserver(String name,String hint) { observerName = name; this.hint = hint; } @Override public void update(Subject subject) information =((WeatherSubject)subject).getInformation(); System.out.println(observerName+"收到了"+information+"的通知"+","+hint); } } package com.pattern.observer; //测试类 public class TestObserverPattern { public static void main(String[] args) { //1.创建目标对象 WeatherSubject subject = new WeatherSubject(); //2.创建观察者对象 ConcreteObserver observerOne = new ConcreteObserver("Tom", "已收到,考虑是否去购物"); ConcreteObserver observerTwo = new ConcreteObserver("Jake", "已收到,考虑是否去旅游"); //3.添加观察者 subject.add(observerOne); subject.add(observerTwo); //4.更新目标状态信息 subject.setInformation("天气晴朗"); } }
在设计观察者模式的时候,由于对于向观察者对象传送的消息内容的不同,观察者模式又分为推模型和拉模型; 拉模型:将目标对象传给观察者对象,观察者对象需要目标对象的哪一部分的状态信息,就通过该目标对象获取信息;当观察者对象对更新信息的需求发生变化时,拉模型可以很好地应对变化的场景;在上述的例子中,采用的是拉模型进行观察者模型的设计; 推模型:将指定的更新信息通知给观察者对象,当观察者对更新信息有了不同的要求之后,这种方式将会显得难以适应变化的要求; 如果想将上述例子通过推模型实现,只需要对具体观察者类中的update进行修改和对具体目标类中的notifyAllObservers进行重写;修改如下: public void notifyAllObservers() { for (Observer observer : list) { //将传入观察者对象的update方法 observer.update(information); } } public void update(String information) { this.information = information; System.out.println(observerName+"收到了"+information+"的通知"+","+hint); } 在Java中,其实提供了观察者模式的实现,利用java.util包下的Observable类和Observer接口就可以大大简化我们自己设计观察者模式的步骤;利用Java提供的观察者模式的实现将上述例子重新进行设计:
/** *目标类的设计 */ package com.pattern.observerInJava; import java.util.Observable; public class ConcreteSubject extends Observable { private String weatherInfor;//天气信息 public String getWeatherInfor() { return weatherInfor; } public void setWeatherInfor(String weatherInfor) { this.weatherInfor = weatherInfor; //使用Java提供的观察者模式,在进行通知观察者更新信息之前所必需的一步 this.setChanged(); //设置拉模型,将目标对象直接传到观察者方法中 this.notifyObservers(); //设置推模型,将具体需要通知的信息传到观察着方法中 this.notifyObservers(weatherInfor); } } /** *观察者类的设计 */ package com.pattern.observerInJava; import java.util.Observable; import java.util.Observer; public class ConcreteObserver1 implements Observer { private String observerName; private String weatherInfor; public ConcreteObserver1(String name) { observerName = name; } @Override public void update(Observable o, Object arg) { //采用拉模型进行观察者消息的更新 weatherInfor = ((ConcreteSubject)o).getWeatherInfor(); System.out.println(observerName+"从目标处拉取了更新的信息"); System.out.println(observerName+"收到了"+weatherInfor); //采用推模型进行观察者消息的更新 System.out.println(observerName+"接收到了推动的更新的信息"); System.out.println(observerName+"收到了"+weatherInfor); } } /** *测试类的设计 */ package com.pattern.observerInJava; import com.pattern.observerInJava.ConcreteObserver1; public class TestObserverInJava { public static void main(String[] args) { //1.创建目标对象 ConcreteSubject subject = new ConcreteSubject(); //2.创建观察者对象 ConcreteObserver1 observerOne = new ConcreteObserver1("Tom"); ConcreteObserver1 observerTwo = new ConcreteObserver1("Jake"); //3.添加观察者 subject.addObserver(observerOne); subject.addObserver(observerTwo); //4.更新目标状态信息 subject.setWeatherInfor("天气晴朗"); } }
进一步地提出问题,当不同的观察者对象对目标对象的更新信息中感兴趣的方面不同,比如观察者对象A只对下雨天和阴天感兴趣,观察者对象B只对下雨天感兴趣,这时,将需要根据不同的需求向不同的观察者对象发送相应的更新信息; 这里可以使用面向接口编程的思想进行解决,设计一个抽象目标类,在该类中实现其具体实现类中公有的部分,而将notifyAllObservers方法放在其具体实现类中进行实现,在该方法中根据需求的不同进行不同的处理; notifyAllObservers方法的具体实现可参考如下代码: public void notifyAllObservers() { for (Observer observer : list) { //如果天气为下雨天,则只向观察者A、B推送更新信息 if("下雨天".equals(weatherInfor)) { if(observer.getObserverName.equals("A")) { observer.update(this); } if(observer.getObserverName.equals("B")) { observer.update(this); } } //如果天气为阴天,则指向观察者A推送更新信息 if("阴天".equals(weatherInfor)) { if(observer.getObserverName.equals("A")) { observer.update(this); } } } } 在当自己进行观察者模式设计的时候,这里给出一些适用于观察者模式设计的注意点: ①命名上的建议: 目标接口定义为Subject 观察者接口定义为Observer 观察者接口中的的更新方法定义为update ②触发通知的时机应该在更新完目标对象的状态信息之后通知 ③通知的顺序:观察者之间是平行的,在观察者模式中不需要指定通知的顺序 观察者模式设计流程分析: 准备阶段 1、创建目标对象 2、创建观察者对象 3、在目标对象中注册观察者对象 运行阶段 1、改变目标对象的状态 2、通知所有已注册观察者对象进行相应的处理 3、回调目标对象,获取相应数据 观察者优点及适用场景: 优点: ①观察者模式实现了观察者和目标之间的抽象耦合; ②观察者模式实现了动态联动; ③观察者模式支持广播通信; 使用场景: ①在一个业务场景中,某一方面的操作需要依赖另一方面状态的改变; ②在更改一个对象的状态同时,需要连带着修改其他对象的状态,并且需要被连带修改的对象的个数不知道; ③当需要实现通知对象和被通知对象之间的松散耦合的时候,选用观察者模式;
相关文章推荐
- java设计模式学习(一):观察者模式(一)
- Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式
- 设计模式学习总结(15) 观察者模式
- Java-马士兵设计模式学习笔记-观察者模式-读取properties文件,动态增加观察者
- 黑马程序员——Java学习笔记之12——已接触的“设计模式”总结
- JAVA设计模式学习总结
- java学习笔记-设计模式16(观察者模式)
- 学习Java设计模式之观察者模式
- Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button
- java 设计模式学习笔记(12) - 观察者模式
- 黑马程序员--Java学习日记之总结复习(多线程和设计模式)
- Java设计模式学习心得总结
- java设计模式学习之观察者模式(一)
- Java-马士兵设计模式学习笔记-观察者模式-AWT简单例子
- java的设计模式,学习心得总结-工厂模式
- 设计模式学习笔记---观察者模式Observer pattern(Java版)
- java学习之观察者设计模式
- java的设计模式,学习心得总结-工厂模式
- java设计模式学习系列之六:Observer, 观察者模式---小例
- 11. JAVA常用类库 Part 4 (对象克隆技术clone、Arrays类、Comparable接口、比较器Comparator、观察者设计模式) ----- 学习笔记