设计模式之观察者模式
来源:互联网 发布:银行证券软件下载 编辑:程序博客网 时间:2024/06/06 20:17
在慕课网上学习了观察者模式,故做个笔记温习巩固一下http://www.imooc.com/learn/415
自己写一个经典观察者模式
观察者模式定义
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到了通知并自动更新。
好处:统一通知,各自处理。
认识观察者(六大方面):
1、目标与观察者之间的关系(1VS1、1VSn、nVS1)
2、单向依赖(又称为订阅发布模式)
3、命名建议
1、目标接口的定义,建议在名称后跟Subject
2、观察者接口的定义,建议在名称后跟Observer
3、观察者接口的更新方法,建议命名为update,参数个数及类型不受限制。
4、触发通知的时机(完成状态维护后触发)
5、观察者模式的调用
6、通知的顺序(多个观察者之间的关系是平行的,不可以有依赖关系)
以下为一个经典的观察者模型。
package com.observer;import com.subject.Subject;/** * 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象 * * @author Administrator * */public interface Observer { /** * 更新的接口 * @param subject 传入目标对象,方便获取相应的目标对象的状态 */ public void update(Subject subject);}
package com.observer;import com.subject.ConcreteSubject;import com.subject.Subject;/** * 具体的观察者对象,实现更新的方法 * @author Administrator * */public class ConcreteObserver implements Observer { //观察者的状态 private String observerState; /** * 获取目标类的状态同步到观察者的状态中 */ @Override public void update(Subject subject) { observerState = ((ConcreteSubject) subject).getSubjectState(); }}
package com.subject;import java.util.ArrayList;import java.util.List;import com.observer.Observer;/** * 目标对象,它知道观察它的观察者,并提供注册(添加)和删除观察者的接口 * @author Administrator * */public class Subject { //用来保存注册的观察者对象 private List<Observer> observers = new ArrayList<Observer>(); //attach detach notifyObservers public void attach(Observer observer){ observers.add(observer); } /** * 删除集合中的指定观察者 * @param observer */ public void detach(Observer observer){ observers.remove(observer); } /** * 通知所有注册的观察者对象 */ protected void notifyObservers(){ for (Observer observer : observers) { observer.update(this); } }}
package com.subject;/** * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 * @author Administrator * */public class ConcreteSubject extends Subject{ //目标对象的状态 private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; this.notifyObservers();//通知 }}
推模型和拉模型
推模型:
目标对象主动向观察者推送目标的详细信息
推送的信息通常都是目标对象的全部或部分数据
拉模型:
目标对象在通知观察者时,只传递少量信息
如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据
一般这种模型的实现,会把目标对象通过update方法传递给观察者
比较:
推模型是假定目标对象知道观察者需要的数据
拉模型是目标对象不知道观察者具体需要什么数据,因此把自身传给观察者,由观察者来取值
推模型会使观察者对象难以复用
拉模型下,update方法的参数是目标对象本身,基本上可以适应各种情况的需要。
一下是经典的观察者模型的一个实用的案例
package com.observer;import com.subject.WeatherSubject;/** * 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象 * * @author Administrator * */public interface Observer { /** * 更新的接口 * @param subject 传入目标对象,方便获取相应的目标对象的状态 */ public void update(WeatherSubject subject);}
package com.observer;import com.subject.ConcreteWeatherSubject;import com.subject.WeatherSubject;/** * 具体的观察者对象,实现更新的方法 * * @author Administrator * */public class ConcreteObserver implements Observer { // 观察者的名字,是谁收到了这个讯息 private String observerName; // 天气内容的情况,这个消息从目标出获取 private String weatherContent; // 提醒的内容 private String remindThing; public String getObserverName() { return observerName; } public void setObserverName(String observerName) { this.observerName = observerName; } public String getWeatherContent() { return weatherContent; } public void setWeatherContent(String weatherContent) { this.weatherContent = weatherContent; } public String getRemindThing() { return remindThing; } public void setRemindThing(String remindThing) { this.remindThing = remindThing; } /** * 获取目标类的状态同步到观察者的状态中 */ @Override public void update(WeatherSubject subject) { weatherContent = ((ConcreteWeatherSubject) subject).getWearherContent(); System.out.println(observerName + "收到了" + weatherContent + "," + remindThing); }}
package com.subject;import java.util.ArrayList;import java.util.List;import com.observer.Observer;/** * 目标对象,它知道观察它的观察者,并提供注册(添加)和删除观察者的接口 * @author Administrator * */public class WeatherSubject { //用来保存注册的观察者对象 private List<Observer> observers = new ArrayList<Observer>(); //attach detach notifyObservers /** * 把订阅天气的人添加到观察者列表 * @param observer */ public void attach(Observer observer){ observers.add(observer); } /** * 删除集合中的指定订阅天气的人 * @param observer */ public void detach(Observer observer){ observers.remove(observer); } /** * 通知所有已经订阅天气的人 */ protected void notifyObservers(){ for (Observer observer : observers) { observer.update(this); } }}
package com.subject;/** * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 * @author Administrator * */public class ConcreteWeatherSubject extends WeatherSubject{ //获取天气的内容信息 private String wearherContent; public String getWearherContent() { return wearherContent; } public void setWearherContent(String wearherContent) { this.wearherContent = wearherContent; //内容有了,说明天气更新了,通知所有订阅的人 this.notifyObservers(); }}
package com.test;import com.observer.ConcreteObserver;import com.subject.ConcreteWeatherSubject;public class Client { public static void main(String[] args) { //1、创建目标 ConcreteWeatherSubject weather = new ConcreteWeatherSubject(); //2、创建观察者 ConcreteObserver observerGirl = new ConcreteObserver(); observerGirl.setObserverName("美女"); observerGirl.setRemindThing("约吗?"); ConcreteObserver observerGirl2 = new ConcreteObserver(); observerGirl2.setObserverName("美女2号"); observerGirl2.setRemindThing("约不约?"); //3、注册观察者 weather.attach(observerGirl); weather.attach(observerGirl2); //4、目标发布天气 weather.setWearherContent("明天天气晴朗,蓝天白云"); }}
Java自身也提供了观察者模式
java.util包下的Observable类中含有观察者模式的大部分方法,Observer接口中含有update方法
java实现观察者模式与自身实现的对比:
1、不需要再定义观察者和目标的接口了,JDK帮忙定义了。
2、具体的目标实现里面不需要再维护观察者的注册信息了,这个在Java的Observable类里面已经帮忙实现好了。
3、触发通知的方法有一点变化,需要调用setChanged方法,这个是java为了帮助实现更精确的触发控制而提供的功能
4、具体的观察者实现里面,update方法其实能同时支持推模型和拉模型。这是java在定义的时候,就已经考虑进去了
观察者模式的有点:
1、观察者模式实现了观察者和目标之间的抽象耦合
2、观察者模式实现了动态联动
3、观察者模式支持广播通信
观察者模式的缺点:可能会引起无畏的操作。
以下是使用java自带的观察者模式的一个案例
import java.util.Observable;//天气目标的具体实现类public class ConcreteWeatherSubject extends Observable { //天气情况的内容 private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; //天气情况有了要通知所有的观察者 //注意在通知之前,在调用Java中的Observer模式时,下面这句话必不可少 this.setChanged(); //主动通知,这里使用的是推模型 this.notifyObservers(content); /* * 拉方法,不带参数 * this.notifyObservers(); */ }}
import java.util.Observable;import java.util.Observer;//具体的观察者对象public class ConcreteObserver implements Observer { // 定义观察者名称的对象 private String observerName; @Override public void update(Observable o, Object arg) { //推模式 System.out.println(observerName+"收到了消息,目标推送过来的是:"+arg); //拉模式 System.out.println(observerName+"收到了消息,主动去目标拉取过来的是:"+((ConcreteWeatherSubject)o).getContent()); } public String getObserverName() { return observerName; } public void setObserverName(String observerName) { this.observerName = observerName; }}
public class Client { public static void main(String[] args) { //创建天气作为一个目标,也可以说是被观察者 ConcreteWeatherSubject subject = new ConcreteWeatherSubject(); //创建具体的观察者 ConcreteObserver girl = new ConcreteObserver(); girl.setObserverName("美女"); //创建具体的观察者 ConcreteObserver girl2 = new ConcreteObserver(); girl2.setObserverName("美女2号"); //注册观察者 subject.addObserver(girl); subject.addObserver(girl2); //目标更新天气情况了。 subject.setContent("天气更新了。"); }}
区别对待的观察者模式
观察者模式适用情况:
1、当一个抽象模型有两个方面,其中一个方面的操作依赖于两一个方面的状态变化
2、更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟需要有多少对象需要被连带改变
3、当一个对象必须通知其他的对象,但是你又希望这个对象和其他被通知的对象是松散耦合的。
在以上的案例中,加入不同的观察者希望接收目标的天气预报,而非目标内的天气预报不被接收。可以采用以下的案例。
package com.observer;import com.subject.WeatherSubject;public interface Observer { //更新的接口 public void update(WeatherSubject subject); //设置观察者名称 public void setObserverName(String observerName); //取得观察者名称 public String getObserverName();}
package com.observer;import com.subject.ConcreteWeatherSubject;import com.subject.WeatherSubject;public class ConcreteObserver implements Observer { // 观察者的名称 private String observerName; // 天气情况的内容 private String weatherContent; // 提醒的内容 private String remindThing; @Override public void update(WeatherSubject subject) { weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent(); System.out.println(observerName+"收到了"+weatherContent+","+remindThing); } @Override public void setObserverName(String observerName) { this.observerName = observerName; } @Override public String getObserverName() { return observerName; } public String getWeatherContent() { return weatherContent; } public void setWeatherContent(String weatherContent) { this.weatherContent = weatherContent; } public String getRemindThing() { return remindThing; } public void setRemindThing(String remindThing) { this.remindThing = remindThing; }}
package com.subject;import java.util.ArrayList;import java.util.List;import com.observer.Observer;public abstract class WeatherSubject { //用来保存注册的观察者对象 public List<Observer> observers = new ArrayList<Observer>(); public void attach(Observer observer){ observers.add(observer); } public void detach (Observer observer){ observers.remove(observer); } protected abstract void notifyObserver();}
package com.subject;import com.observer.Observer;public class ConcreteWeatherSubject extends WeatherSubject { // 晴天、下雨、下雪 // 目标对象的状态 private String weatherContent; @Override protected void notifyObserver() { // 循环所有注册的观察者 for (Observer observer : observers) { // 规则是: // 黄明的女朋友需要“下雨”的条件 // 黄明的老妈需要“下雪”或者“下雨”的条件 // 如果天气是晴天 // do nothing // 如果天气是下雨 if ("下雨".equals(this.getWeatherContent())) { if ("黄明的女朋友".equals(observer.getObserverName())) { observer.update(this); } if ("黄明的老妈".equals(observer.getObserverName())) { observer.update(this); } } // 如果天气是下雪 if ("下雪".equals(this.getWeatherContent())) { if ("黄明的老妈".equals(observer.getObserverName())) { observer.update(this); } } } } public String getWeatherContent() { return weatherContent; } public void setWeatherContent(String weatherContent) { this.weatherContent = weatherContent; this.notifyObserver(); }}
package com.test;import com.observer.ConcreteObserver;import com.subject.ConcreteWeatherSubject;public class Client { public static void main(String[] args) { //1、创建目标 ConcreteWeatherSubject weatherSubject = new ConcreteWeatherSubject(); //2、创建观察者 ConcreteObserver observerGirl = new ConcreteObserver(); observerGirl.setObserverName("黄明的女朋友"); observerGirl.setRemindThing("下雨了,安静的呆在家里吧"); ConcreteObserver observerMum = new ConcreteObserver(); observerMum.setObserverName("黄明的老妈"); observerMum.setRemindThing("不管下雨还是下雪,都不出门了"); //3、注册观察者 weatherSubject.attach(observerGirl); weatherSubject.attach(observerMum); //4、目标发布天气 weatherSubject.setWeatherContent("下雨"); System.out.println("+++++++++++++++++"); weatherSubject.setWeatherContent("下雪"); System.out.println("+++++++++++++++++"); weatherSubject.setWeatherContent("晴天"); }}
- 设计模式之-观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- android-async-http开源项目介绍及使用方法
- 项目管理工具---maven
- string类的常用的几个小东西find,substr
- 穿过已知点画平滑曲线(3次贝塞尔曲线)
- nutch源代码阅读心得
- 设计模式之观察者模式
- hdu 4496(并查集的边删除)
- Android通知代码
- Android Studio使用gradle打包指定包名和类的jar
- 使用WebRTC搭建前端视频聊天室——入门篇
- 关于oracle实例即localhost:1521/orcl中的orcl
- sql server常用函数
- 论Android网络请求库——android-async-http
- 线性代数中向量、矩阵深度理解(PartI)