设计模式之旅(三)--观察者模式
在上一站中,我们了解了木叶村最神秘宇智波一族,接下来这一站,我想我们还是从木叶非常著名的几位实业家开始说起吧...
丁次:对,就是那个胖胖的小伙,他不仅喜欢吃团子,而且他还挺有商业头脑,自己开了一家团子店,可是,自从开业之后,就有一个问题一直在困扰他,就是他做的团子时好时坏,后来,他终于发现了其中的奥秘,是自己对木叶的气温没有把握好-_- 天气多变,温度多变,而自己的的制作工艺没有变化,自然团子的口味不一样,所以说,丁次有一个迫切的需求就是要随时了解木叶的温度变化。
自来也:好色仙人,最近发展了一批小伙伴,培育了一众小青蛙,不过,由于不了解空气湿度的变化,不能及时为小伙伴提供良好的服务,所以自来也老师最近有一个愿望,想要及时的了解木叶的湿度变化。
志乃:子承父业,志乃继承了父亲的衣钵,将家族的虫子养殖事业发展的越来越大,他需要更多的了解木叶的天气变化,他要随时的了解木叶的温度 气压 湿度。
就这样,在同一天,这三人同时来到了木叶气象局,要求气象局能够在自己的家里安装一块气象公告板,好及时的显示自己所需要的气象数据。值班的是鸣人-_-,鸣人是个热心人,当场就答应了三位,”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,源码下载
设计模式之旅(三)--观察者模式相关推荐
- Javascript乱弹设计模式系列(1) - 观察者模式(Observer)
前言 博客园谈设计模式的文章很多,我也受益匪浅,包括TerryLee.吕震宇等等的.NET设计模式系列文章,强烈推荐.对于我,擅长于前台代码的开发,对于设计模式也有一定的了解,于是我想结合Javasc ...
- C#设计模式之十六观察者模式(Observer Pattern)【行为型】
C#设计模式之十六观察者模式(Observer Pattern)[行为型] 原文:C#设计模式之十六观察者模式(Observer Pattern)[行为型] 一.引言 今天是2017年11月份的最后一 ...
- 行为型设计模式(4)—— 观察者模式(Observer Pattern)
文章目录 1.概述 2.实例 2.1 丑陋的设计 2.2 使用观察者模式 3.应用场景 4.优缺点 5.小结 参考文献 1.概述 使用设计模式可以提高代码的可复用性.可扩充性和可维护性.观察者模式(O ...
- php设计模式课程---4、观察者模式的好处是什么
php设计模式课程---4.观察者模式的好处是什么 一.总结 一句话总结: 方便选择之后去控制监听的板块数:比如选择男士之后,我可以决定监听广告里面的第二和第三板块. 1.为什么有观察者模式? 错误理 ...
- 《大话设计模式(C#实现)》(Yanlz+VR云游戏+Unity+SteamVR+云技术+5G+AI+设计模式+GoF+UML+单例模式+观察者模式+抽象工厂+代理模式+框架编程+立钻哥哥++OK+)
<大话设计模式(C#实现)> 版本 作者 参与者 完成日期 备注 YanlzFramework_GoF_V01_1.0 严立钻 2020.02.10 ##<大话设计模式(C#实现)& ...
- PrintJ的设计模式之旅——1.模式之父
好奇设计模式的源头,做了一番搜索和调查,于是便开启了这个系列"PrintJ的设计模式之旅". 1.模式之父 GOF(Gang of Four) Erich Gamma.Richar ...
- HALCON学习之旅(三)
HALCON学习之旅(三) 文章目录 HALCON学习之旅(三) 1.创建自适应图形窗口 2.霍夫变换寻找图像直线 1.创建自适应图形窗口 原因:默认的图形窗口尺寸为512*512.当图像变量尺寸与图 ...
- 面试官:Spring 用了哪些设计模式?说三种即可 = =
面试官:Spring 用了哪些设计模式?说三种即可 = = 转载:https://mp.weixin.qq.com/s/LGD54XaK4RmhZHxtU0BADg 转载理由:还可以
- 设计模式混编:观察者模式+中介者模式
针对变化万千的业务需求,采用合适的设计模式是可以轻松应对的. 本文将探索多种优秀设计模式的混编来解决复杂场景的问题,实现1+1>2的效果.应用实践离不开基础,所以文章将以基本概念.设计初衷出发, ...
- 打怪升级之小白的大数据之旅(三十一)<JavaSE总结>
打怪升级之小白的大数据之旅(三十) JavaSE总结 引言 Java这只小怪物我们已经练级差不多了,明天我们将进入新的旅程了,所以,我要对前面的整个JavaSE知识点进行总结,就像积攒够了经验升级一样 ...
最新文章
- python比c语言开发速度快多少倍_Python语言其实很慢,为什么机器学习这种快速算法步骤通常还是用呢?...
- java mongodb 使用MongoCollection,BasicDBObject 条件查询
- 欢迎关注我的微信公众号 “我是一个假的程序猿”
- Markdown中数学公式整理
- 黑马程序员---面向对象笔记总结
- 【Java】时间的新旧比较
- merlin.acs的使用方法 merlin.acs添加右键菜单
- C#中get和SET
- 调试at91-sama5d27遇到的一些问题(3)
- javascript 设为首页 | 加入收藏夹 JS代码
- volte的sip信令流程_VOLTE-SIP完整信令解析
- Unicode(全世界每个国家字符的唯一编码0x000000 到 0x10FFFF)与UTF-8的区别
- 台式计算机 cpu型号大全,电脑cpu的型号有哪些?
- N个元素中选最大最小
- 计算机正常开机显示器无信号,电脑开机显示器无信号怎么办 电脑开机显示器无信号解决方法【详解】...
- 真实世界里的钢铁侠-特斯拉汽车创始人埃隆#183;马斯克(Elon Musk)
- 小宝精灵-智能语音遥控伴侣(套装版)测评-遥控器的语音时代
- springsecurity与gateway网关整合配置
- 【ora-12528】数据库服务器重启之后,出现ora-12528:所有适用例程都无法建立新连接
- 用python构建多只股票日收益率直方图_Barra纯因子收益率的Python实现
热门文章
- transform.forward和vector3.forward的使用区别
- 祝你生日快乐+两只老虎简谱
- 工程经济有何难,思维导图来助阵
- Mac 使用mysql出现ERROR [MY-013183][InnoDB] Assertion failure以及找不到my.cnf的解决过程
- 交叉编译openssl
- 1.DingoApi安装和配置
- UVA 12304 /// 圆的综合题 圆的模板
- 数据分析之Pandas(三):汇总、统计、相关系数和协方差
- BiLSTM文本分类实践
- twitter验证_如何在Twitter上进行验证(或至少尝试一下)