设计模式之旅(三)--观察者模式
来源:互联网 发布:数据朔源技术的目标 编辑:程序博客网 时间:2024/06/04 19:01
在上一站中,我们了解了木叶村最神秘宇智波一族,接下来这一站,我想我们还是从木叶非常著名的几位实业家开始说起吧...
丁次:对,就是那个胖胖的小伙,他不仅喜欢吃团子,而且他还挺有商业头脑,自己开了一家团子店,可是,自从开业之后,就有一个问题一直在困扰他,就是他做的团子时好时坏,后来,他终于发现了其中的奥秘,是自己对木叶的气温没有把握好-_- 天气多变,温度多变,而自己的的制作工艺没有变化,自然团子的口味不一样,所以说,丁次有一个迫切的需求就是要随时了解木叶的温度变化。
自来也:好色仙人,最近发展了一批小伙伴,培育了一众小青蛙,不过,由于不了解空气湿度的变化,不能及时为小伙伴提供良好的服务,所以自来也老师最近有一个愿望,想要及时的了解木叶的湿度变化。
志乃:子承父业,志乃继承了父亲的衣钵,将家族的虫子养殖事业发展的越来越大,他需要更多的了解木叶的天气变化,他要随时的了解木叶的温度 气压 湿度。
就这样,在同一天,这三人同时来到了木叶气象局,要求气象局能够在自己的家里安装一块气象公告板,好及时的显示自己所需要的气象数据。值班的是鸣人-_-,鸣人是个热心人,当场就答应了三位,”OK,我立马给大家拿出设计方案“
鸣人还是很靠谱的,拿出了设计图,就给三个人分析了目前的情况:
看,关于气象信息的收集这都是我们气象局的事情,我们给你们设计好一个WeatherData类,当一旦有气象更新时,立马将您所需的气象信息给呈现出来,然后刷刷刷的在机器上码出了以下例子:
public class WeaterData {//...部分代码public void weatherChange(){float temp = getTemperature();float humidity = getHumidity();float pressure = getPressure();board_One.update(temp, humidity, pressure);board_Two.update(temp, humidity, pressure);board_Three.update(temp, humidity, pressure);}}
三位客户正在研究着鸣人的设计方案,鸣人有点小得意,这时,在一旁的雏田,好像有话要说,不断的拉鸣人的衣角。。。
雏田将鸣人拉出去,说:
这个设计,都是针对具体实现进行的编程,这样以后如果鹿丸、卡卡西老师....他们如果也需要气象信息时,我们那必须要修改程序的代码了,这样对代码的维护性及可扩展性都是很大的挑战啊;而且,你再看,后面我们传递的参数都是一样的,这是这个项目中共有的部分,这种统一的地方,我们是不是应该考虑进行封装起来啊
鸣人大惊失色,才发现自己刚才实在太大意了,问雏田有什么好的解决办法,雏田也是不知道改怎么办。。。
这时,雏田,发现了桌子上的报纸,突然想到了一件事情,说,我们可以向佐助的报社学习啊!
”怎么说?“
雏田继续说,我们大家都是向佐助的报社订阅报纸,就像下面这样:
大家想订就订,想退订就退订,这样大家都很方便的。佐助不需要为每一个订购者提供单独的服务,所有的订购者均被一视同仁。订购者,也是如果不想订阅,可以随时取消订阅。
哈哈,鸣人大笑,原来佐助也挺聪明的嘛,这不就是卡卡西老师教的招数嘛,就是使用了:
观察者模式:定义了对象之间的一对多依赖关系,这样一来,当对象的状态改变时,他的所有依赖这都会收到通知并完成自动更新
鸣人仔细想过之后对雏田说,我有办法了,看我设计一个超棒的系统的,先给你看看什么是观察者模式:
在这个模式中,关键是定义两个接口,subject、observer接口,subject接口主要用于定义注册、删除、通知这三个方法,observer接口则主要是定义update方法,提供观察者统一的方法接口,当然观察者可能还有一些可选的公共方法,可以另外写一个接口进行定义。当然,针对接口编程可以实现较好的解耦,如果对此不是很理解,那就接下来继续听鸣人说吧。
以我们的气象站为例,我们首先定义subject及observer接口:
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); }
public interface Observer { public void update(float temp, float humidity, float pressure); }然后就要考虑实现具体的接口了,先看实现subject接口
import java.util.ArrayList; public class WeatherData implements Subject { private ArrayList observers; private float temp; private float humidity; private float pressure; public WeatherData(){ observers = new ArrayList(); } public void setMeasurements(float temp, float humidity, float pressure){ this.temp = temp; this.humidity = humidity; this.pressure = pressure; measurementsChange(); } public void measurementsChange(){ notifyObserver(); } @Override public void registerObserver(Observer o) { // TODO Auto-generated method stub observers.add(o); } @Override public void removeObserver(Observer o) { // TODO Auto-generated method stub int i = observers.indexOf(o); if(i>=0){ observers.remove(i); } } @Override public void notifyObserver() { // TODO Auto-generated method stub for(int i=0;i<observers.size();i++){ Observer observer = (Observer) observers.get(i); observer.update(temp, humidity, pressure); } } }在这个类中保存了一个观察者的ArrayList,所有的观察者的应用都保存在其中。可以进行注册、删除、通知观察者(具体的代码实现,自行体会~~)
在所有的观察者中,我们又发现有其他的公共方法 display(),所以定义此接口:
public interface DisplayElement { public void display(); }那么接下来,看看观察者的实现吧
public class CurrentConditionDisplay implements Observer, DisplayElement { private float temp; private float humidity; private float pressure; private Subject weatherData; public CurrentConditionDisplay(Subject weatherData){ // 保存引用是为了以后更方便的取消注册 this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void display() { // TODO Auto-generated method stub System.out.println("AAA current tempreature is: "+temp+" , humidity is: "+humidity+" , pressure is: "+pressure); } @Override public void update(float temp, float humidity, float pressure) { // TODO Auto-generated method stub this.temp = temp; this.humidity = humidity; this.pressure = pressure; display(); } public Subject getWeatherData() { return weatherData; } public void setWeatherData(Subject weatherData) { this.weatherData = weatherData; }另外两个具体的观察者,啊,不对,太投入了,忘记了这是鸣人在设计天气显示板,另外两个具体的天气显示板,大家可以自行添加哈,当然,依据个人喜好,酌情添加都没问题
好了,最后咱们写一个测试类试一下(如果有类在上面的代码中未实现,请自行补全,当然,在文章底部,提供完整代码下载)
public class Main { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData); CurrentPressure currentPressure = new CurrentPressure(weatherData); CurrentTemp currentTemp = new CurrentTemp(weatherData); CurrentPressure currentPressure2 = new CurrentPressure(weatherData); //在布告板中保存注册主题的引用,可以方便的进行取消注册 currentTemp.getWeatherData().removeObserver(currentTemp); weatherData.removeObserver(currentPressure2); weatherData.setMeasurements(80, 30, 30.4f); }
扯远了,继续说木叶那三位哈,他们看过鸣人的设计之后拍手大赞,自来也老师手舞足蹈的说道,”鸣人你很棒啊,遵循了针对接口编程的原则,为交互对象之间的松耦合设计做了很多努力,即使有新的观察者出现,我们也可以方便的添加,并且我们可以独立的复用主题和观察者,因为二者并非紧密耦合的“
这时,鸣人竟然语重心长的说,老师啊,给你出个问题,你现在是观察者的身份,有没有想过你也可以成为主题呢,在接受我的天气信息之后,既用于个人使用,也销售给你的订阅者们^_^
好吧,自来也老师有点手足无措了(好吧,大家可以想一下下)
说好的源码在这里,请戳HERE,源码下载
- 设计模式之观察者模式(三)
- 设计模式之旅(三)--观察者模式
- IOS设计模式之三(适配器模式,观察者模式)
- iOS设计模式之三(适配器模式,观察者模式)
- iOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- IOS设计模式之三(适配器模式,观察者模式)
- 设计模式系列之三观察者模式
- 设计模式之三:观察者模式
- 设计模式之三:观察者模式
- Unity3D设计模式之观察者模式(16)(三)
- Unity3d之设计模式(三)观察者模式
- 设计模式之——观察者模式(三)
- 设计模式(三)观察者模式
- 第193天
- Moving Tables
- leetcode - Evaluate Reverse Polish Notation
- 浅显讲解perl的模式匹配
- 查看 SELinux状态及关闭SELinux
- 设计模式之旅(三)--观察者模式
- LeetCode Permutations II
- Application reference
- 小米手机照片误删除如何恢复
- LINUX 内核API 改变
- C语言输入输出语句体验算法
- Intent常见用法
- java.lang.ClassNotFoundException: org.springframework.context.ContextLoaderListener
- AVStream ddk 翻译