设计模式 ----- 观察者模式
来源:互联网 发布:js下拉框默认选中 编辑:程序博客网 时间:2024/06/05 03:37
设计模式 —– 观察者模式
个人博客,想要搭建个人博客的可以进来看看: http://www.ioqian.top/
观察者模式,在对象之间定义一对多的依赖,当一个对象状态改变时,依赖他的对象就会收到通知。典型的实现是java swing中的组件监听事件,当我们点击按钮时会调用我们注册的回调函数;还有Rxjava等等
背景
我们是一个天气台,有许多客户,当我们天气信息更新时,我们需要通知用户进行刷新…,我们要利用的是观察者模式
观察者模式主要由下面几部分组成:
- Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象
- WeatherData :具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知
- Observer:抽象观察者,是观察者者的抽象类,它是一个接口,里面有一个很重要的方法,当具体主题状态改变时,直接调用这个方法,这里实现了松耦合
- BoardCallOne :具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
结合我们的背景和下面的代码,我们天气台就是一个具体主题,我们的客户就是具体观察者,我们这里抽象出了两个接口是为了实现松耦合
松耦合设计原则
当两个对象松耦合时,他们可以互相交互,但是不太清楚彼此之间的细节,我们这里让主题和观察者之间松耦合
我们怎么利用接口实现的松耦合哪?
- 关于观察者的一切,主题只知道观察者实现了Observer接口,主题不需要知道具体的观察者是谁,有什么细节,只要继承了Observer接口,有update()实现方法就可以
- 任何时候都可以增加新的观察者,因为主题仅仅依赖了Observer接口,我们可以随时增加或者删除观察者
- 有新的观察者时,主题的代码不要修改
抽象主题 Subject
public interface Subject { //该方法把任意的观察者加入到观察者集合 public void registerObserver(Observer o); //该方法把观察者从观察者从集合中除去,从此收不到状态改变 public void removeObserver(Observer o); //当状态改变时通过观察者集合中的所以观察者 public void notifyAllObserver();}
抽象观察者 Observer
public interface Observer { public void update(float temp,float humidity);}
具体主题 WeatherData
public class WeatherData implements Subject { //观察者集合 private List<Observer> observers; //模拟自身状态,当这些状态改变时通知所有观察者 private float temperature; private float humidity; public WeatherData(){ observers = new ArrayList<>(); } //模拟状态改变通知所有观察者 public void stateChanged(float temp , float humidity){ this.temperature = temp; this.humidity = humidity; notifyAllObserver(); } //模拟状态改变通知所有观察者 public void stateChanged(){ notifyAllObserver(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if(i>=0){ observers.remove(i); } } @Override public void notifyAllObserver() { for(Observer o : observers){ //这里很关键,这里调用的是抽象观察者的方法,不需要明白谁是观察者,只要继承了Observer的类就可以 o.update(temperature , humidity); } }}
具体观察者 BoardCallOne
public interface DisplayDevice { public void display();}//继承DisplayDevice接口和观察者模式没什么联系public class BoardCallOne implements Observer ,DisplayDevice { private static final String TAG = "BoardCallOne"; private float temp; private float humidity; //抽象主题主题 private Subject weatherData ; public BoardCallOne(Subject weatherData) { this.weatherData = weatherData; //作为观察者,注册主题 weatherData.registerObserver(this); } //取消注册 public void removeRegister(){ weatherData.removeObserver(this); } //作为观察者必须实现的方法,所有当具体主题状态变化会通知我,我本身调用display()方法,实时刷新天气信息 @Override public void update(float temp, float humidity) { this.temp = temp; this.humidity = humidity; display(); } @Override public void display() { System.out.println(TAG + " i get info from weather data {temp="+temp+",humidity="+humidity+"}"); }}
测试main
public class Main { public static void main(String[] args) throws InterruptedException { //具体主题实现这 WeatherData subject = new WeatherData(); //具体观察者,在观察者的构造方法中注册了主题 BoardCallOne boardCallOne = new BoardCallOne(subject); //在线程中一直让主题去通知观察者10次,每次休息1s Thread t = new Thread(new Runnable() { @Override public void run() { for(int i = 0 ; i < 10 ;i++){ try { subject.stateChanged(10.0f,18.0f); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); //主线程休眠5s后观察者取消注册,所以结果是会打印5次消息通知 Thread.sleep(5000); boardCallOne.removeRegister(); //等待子线程结束 t.join(); }}结果验证了我们的猜测BoardCallOne i get info from weather data {temp=10.0,humidity=18.0}BoardCallOne i get info from weather data {temp=10.0,humidity=18.0}BoardCallOne i get info from weather data {temp=10.0,humidity=18.0}BoardCallOne i get info from weather data {temp=10.0,humidity=18.0}BoardCallOne i get info from weather data {temp=10.0,humidity=18.0}Process finished with exit code 0
总结
1.我们这里的是push模式,push模式是主题状态改变去通知所有观察者;还有pull,观察者可以主动去获取主题的状态
2.观察者模式用到了那些设计原则
- 变化分离原则,在观察者模式中,会改变的是主题的状态,及观察者的类型和数目,我们可以改变改变依赖于主题的对象,不必改变主题
- 针对接口编程原则,主题和观察者都使用了接口。观察者利用主题的接口进行向主题注册(在代码具体观察者的构造函数中);主题利用接口通知观察者,实现了松偶尔
- 多用组合,少用继承 ,利用组合把众多观察者包含进主题,private List observers;
- 模式设计:观察者模式
- 设计模式-----观察者模式
- 设计模式-观察者模式
- 设计模式--观察者模式
- 设计模式:观察者模式
- 设计模式-----观察者模式
- 设计模式:观察者模式
- 设计模式-观察者模式
- 设计模式 观察者模式
- 设计模式-观察者模式
- 设计模式-【观察者模式】
- 设计模式-观察者模式
- 设计模式 -- 观察者模式
- 设计模式-观察者模式
- 【设计模式】观察者模式
- 设计模式- 观察者模式
- 设计模式- 观察者模式
- 设计模式--观察者模式
- JM在visual studio 上运行
- javascript学习笔记
- pointers on c 编程练习 6-2
- Android之Keystore文件签名(获取查看apk签名)
- SQLiteOpenHelper一些疑问点
- 设计模式 ----- 观察者模式
- SQL数据查询及常见约束
- Java面向对象(五)abstract --- 抽象
- 「转」 python中try except处理程序异常的三种常用方法
- jenkins的war包下载
- Sublime Text 3中文显示乱码问题
- 分治法-递归-汉诺塔问题
- jQuery 事件委托
- 三个案例带你看懂LayoutInflater中inflate方法两个参数和三个参数的区别