Observer Pattern
问题:
有一个气象站(WeatherData),用来给各种手机(苹果,三星,摩托罗拉等等)提供气象信息,要求是,当气象信息更新的时候,给各个手机发送新的天气信息。
方案一
//Iphone类 package com.pattern.observer; /** * 苹果手机 */ public class Iphone { /** * 苹果手机用来显示天气的方法 */ public void display(float low,float height,String weather){ System.out.println("Iphone:最低温度-"+low+",最高温度-"+height+",天气"+weather+"。"); } }
//Android类 package com.pattern.observer; /** * 安卓手机 */ public class Android { /** * 安卓手机用来显示天气的方法 */ public void display(float low,float height,String weather){ System.out.println("Android:最低温度-"+low+",最高温度-"+height+",天气"+weather+"。"); } }
//WeatherData类 package com.pattern.observer; /** * 用来给手机厂商提供天气信息的公共类 */ public class WeatherData { private float low;//最低气温 private float height;//最高气温 private String weather;//天气情况 /** * 提供给气象人员用来更新天气信息的,当天气更新时,掉用changed方法 */ public void setData(float low,float height,String weather){ this.low=low; this.height=height; this.weather=weather; changed(); } /** * changed方法,用来给接入的手机发送天气信息 */ private void changed() { //苹果接入,给苹果手机提供天气服务 Iphone iphone=new Iphone(); iphone.display(getLow(), getHeight(), getWeather()); //安卓接入,给安卓手机提供天气服务 Android android=new Android(); android.display(getLow(), getHeight(), getWeather()); } public float getLow() { return low; } public float getHeight() { return height; } public String getWeather() { return weather; } }
//Test类 package com.pattern.observer; public class Test { public static void main(String[] args) { WeatherData wd=new WeatherData(); //天气人员更新天气,手机显示更新的天气 wd.setData(32, 41, "晴天"); } }
方案一的问题
如果不断有手机厂商需要接入我们的天气服务,或者不断有手机厂商不需要我们的天气服务了,我们就得不停的改动WeatherData类,这是很麻烦的事情。
问题的解决
拿出版社来举例说明
- 出版社的任务就是出版报纸
- 你订阅了报纸,出版社就给你送
- 你不需要该报纸了,你可以退订
- 气象站一直提供气象服务
- 气象站提供一个定制服务
- 你定制了,就给你送,你取消定制了,就不给你送了
观察者模式
- 定义了对象间 一对多 的依赖
- 报社→一
- 订阅者→多
- 订阅者是观察者的对象
方案二
//Subject接口 package com.pattern.observer1; /** *提供订阅服务的接口 */ public interface Subject { public void registerObserver(Observer observer);//注册观察者 public void removeObserver(Observer observer);//删除观察者 public void notifyObserver();//通知观察者 }
//Observer接口 package com.pattern.observer1; /** * 观察者接口,实现此接口后方可去订阅主题,天气主题的观察者需要提供显示天气的方法 */ public interface Observer { //观察者必须实现此方法,用来显示天气 public void display(float low,float height,String weather); }
//WeatherData类 package com.pattern.observer1; import java.util.ArrayList; import java.util.List; /** * 天气数据提供订阅,实现主题接口 */ public class WeatherData implements Subject{ private float low; private float height; private String weather; private List<Observer> args=new ArrayList<Observer>();//当前气象站具有的观察者集合 public float getLow() { return low; } public float getHeight() { return height; } public String getWeather() { return weather; } public void setData(float low,float height,String weather){ this.low=low; this.height=height; this.weather=weather; changed(); } private void changed() { notifyObserver(); } /** * 注册观察者,如果集合中不存在,则添加进集合 */ @Override public void registerObserver(Observer observer) { if(!args.contains(observer)){ args.add(observer); } } /** * 删除观察者,若存在此观察者,删除此观察者 */ @Override public void removeObserver(Observer observer) { if(args.contains(observer)){ args.remove(observer); } } /** * 数据改变时,调用此方法,给每一个观察者发送改变后的信息 */ @Override public void notifyObserver() { for (Observer o : args) { o.display(getLow(), getHeight(), getWeather()); } } }
//Iphone类 package com.pattern.observer1; /** * Iphone实现观察者接口,是一名观察者,是否订阅天气,看采用哪一种构造方法 */ public class Iphone implements Observer{ public Iphone(){ } /** * 注册天气信息,在气象站注册信息,this指当前对象 */ public Iphone(Subject sub){ sub.registerObserver(this); } /** * 当成为气象站的观察者后,天气发生改变后,会收到通知,调用此方法 */ @Override public void display(float low, float height, String weather) { System.out.println("Iphone:最低温度-"+low+",最高温度-"+height+",天气"+weather+"。"); } }
//Test类 package com.pattern.observer1; public class Test { @SuppressWarnings("unused") public static void main(String[] args) { WeatherData wd=new WeatherData(); Iphone i=new Iphone(wd);//i手机注册天气服务 Iphone i2=new Iphone(wd);//i2手机也注册天气服务 wd.removeObserver(i);//气象站取消了i手机的订阅 wd.setData(23, 25, "windy");//这里只给i2提供天气服务 } }
方案三
Java内置的观察者模式(Observable-Observer)
//Observable类 package com.pattern.observer2; import java.util.Vector; @SuppressWarnings("unchecked") public class Observable { private boolean changed = false;//观察者所观察的信息是否改变 @SuppressWarnings("rawtypes") private Vector obs;//用来存放观察者的集合 /** * 构造一个没有观察者的Observable对象 */ @SuppressWarnings("rawtypes") public Observable() { obs = new Vector(); } /** * 线程安全模式下,添加一个观察者 * 如果观察者为null,则抛异常 * 如果当前观察者列表中没有此观察者,则添加进来 */ public synchronized void addObserver(Observer o) { if (o == null){ throw new NullPointerException(); } if (!obs.contains(o)) { obs.addElement(o); } } /** * 删除一个观察者,如果删除的不存在,也没有影响 */ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * 这个方法是notifyObservers方法的重载,用来向所有观察者提供信息的 */ public void notifyObservers() { notifyObservers(null);//调用下面的方法,传入参数null } /** * 如果Observable的状态发生了改变,则通知所有观察者 */ public void notifyObservers(Object arg) { Object[] arrLocal;//临时数组 synchronized (this) { if (!changed){ return;//如果没有改变,则什么也不做 } arrLocal = obs.toArray();//若改变了将obs集合转成数组 clearChanged();//设置changed为false } //给每一个观察者送出通知 for (int i = arrLocal.length-1; i>=0; i--){ ((Observer)arrLocal[i]).update(this, arg); } } /** * 删除所有的观察者 */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * 用来设置Observable对象发生了改变 */ protected synchronized void setChanged() { changed = true; } /** * 所有的观察者都接收到通知后,再把Observable对象设置为未改变 */ protected synchronized void clearChanged() { changed = false; } /** * 判断Observable对象是否改变,返回changed的值 */ public synchronized boolean hasChanged() { return changed; } /** * 统计当前Observale对象中有多少观察者 */ public synchronized int countObservers() { return obs.size(); } }
//Observer接口 package com.pattern.observer2; /** * 所有的观察者都要实现观察者接口 */ public interface Observer { /** * 所有的观察者都要实现update方法,用来接收被观察对象传来的信息 */ void update(Observable o, Object arg); }
//WeatherData类 package com.pattern.observer2; import java.util.Observable; public class WeatherData extends Observable{ private float low; private float height; private String weather; public float getLow() { return low; } public float getHeight() { return height; } public String getWeather() { return weather; } /** * 更新天气,调用changed方法,在changed方法中调用setChanged,notifyObservers */ public void setData(float low,float height,String weather){ this.low=low; this.height=height; this.weather=weather; changed(); } /** * 此方法可有可无,可以将内容写到setData中,无所谓的 */ private void changed() { setChanged(); notifyObservers(); /** * notifyObservers(Object arg)这个方法的作用是啥呢? * 使用notifyObservers()是拉模式,给用户提供获取天气信息的接口,如果需要,通过接口来拿即可 * 带参数的方法,可以用来实现气象站主动给你送天气,你直接用即可 * 例: * notifyObservers(new Object[]{getLow(),getHeight(),getWeather()} * Iphone中的update方法中的ars包含了此数组 * 直接取即可 * args[0] * args[1] * args[2] * */ } }
//Iphone类 package com.pattern.observer2; import java.util.Observable; import java.util.Observer; public class Iphone implements Observer{ public Iphone(){ } /** * 用于注册到一个Observable的观察者 * 如果一个Iphone对象想接收某一个天气站的天气信息,就必须先注册人家的服务 */ public Iphone(Observable sub){ sub.addObserver(this); } /** * 重写update方法 * 如果当前对象注册了,并且信息发生了改变,就给当前对象送来Observable对象o,o中包含有所有的天气信息 * 从o中提起信息即可 */ @Override public void update(Observable o, Object arg) { WeatherData wd=(WeatherData) o; display(wd.getLow(),wd.getHeight(),wd.getWeather()); } private void display(float low, float height, String weather) { System.out.println("Iphone:最低温度-"+low+",最高温度-"+height+",天气"+weather+"。"); } }
//Test类 package com.pattern.observer2; public class Test { public static void main(String[] args) { WeatherData wd=new WeatherData(); Iphone i=new Iphone(wd); wd.setData(12, 28, "sunny"); } }
Java内置观察者的缺点
Observable是一个类,类只能继承一个父类,如果其有自己的父类,则无法继承观察者模式了关于观察者模式
- 该模式定义了对象之间一对多的关联
- 主题用一个共同的接口来更新观察者
- 主题和观察者之间用松耦合的方式结合,主题不知道观察者的细节,只知道观察者实现了观察者接口
相关推荐
基于java的校园美食交流系统设计与实现.docx
均包含代码,文章,部分项目包含ppt
基于python的酒店评论中文情感分析系统源码+设计文档+数据集.zip基于python的酒店评论中文情感分析系统源码+设计文档+数据集.zip基于python的酒店评论中文情感分析系统源码+设计文档+数据集.zip 个人大四的毕业设计、课程设计、作业、经导师指导并认可通过的高分设计项目,评审平均分达96.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 [资源说明] 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设或者课设、作业,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96.5分,放心下载使用! 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),供学习参考。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
基于Django框架开发的协同过滤算法小说推荐系统是一种利用用户行为数据来提供个性化小说推荐的应用。该系统通过分析用户的历史阅读记录、评分和反馈,发现用户之间的相似性或小说之间的相似性,进而为用户推荐可能感兴趣的小说。以下是该系统可能包含的关键特性: 1. **用户账户管理**:允许用户创建账户、登录和编辑个人信息,同时跟踪用户的阅读历史和评分。 2. **小说数据库**:构建一个包含大量小说信息的数据库,每本小说都有详细的元数据,如作者、出版年份、流派、标签等。 3. **协同过滤引擎**:实现协同过滤算法,包括用户-用户协同过滤和项目-项目协同过滤,以发现相似用户或相似小说。 4. **推荐生成**:根据协同过滤引擎的结果,生成个性化的小说推荐列表,并提供给用户。 5. **评分系统**:允许用户对小说进行评分,这些评分数据将用于训练推荐算法,提高推荐的准确性。 6. **用户界面**:设计直观、易用的用户界面,使用户能够轻松浏览推荐的小说、查看详情和进行评分。 7. **搜索和筛选功能**:提供强大的搜索功能,允许用户根据标题、作者或流派等关键词搜索小说,并提供筛选
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
内容概要:本文是关于2020年度数字孪生技术的最新进展和发展趋势的研究报告。文中对数字孪生技术及其应用场景作出了详细的阐述,特别强调了数字孪生在智能制造、智慧城市、产品开发等多个领域内的实际应用成果,并讨论了数字孪生带来的信息安全方面的挑战和解决方案。 适用人群:面向希望深入了解和应用数字孪生技术的企业管理人员、研发工程师和学者。 使用场景及目标:适用于企业或机构寻求改进产品设计、生产制造、城市管理等领域效能的情况,助力相关人员理解和实现更加精细的管理决策和模拟预测,进而优化资源配置与提升工作效率。 其它说明:介绍了多项核心技术,包括但不限于数据收集、建模仿真、模型管理系统等,并分享了多个数字孪生的真实应用案例以展示其实效。
基于java的的德云社票务系统的设计与实现.docx
基于java的宜佰丰超市进销存管理系统设计与实现.docx
基于java的削面快餐店点餐服务系统的设计与实现.docx
用户体验分享和讨论.ppt
均包含代码,文章,部分项目包含ppt
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 、3本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 、本项3目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看ReAdmE.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
均包含代码,文章,部分项目包含ppt
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
志愿者招募网站,在网站首页可以查看首页,组织信息,志愿活动,新闻资讯,个人中心,后台管理等内容,并进行详细操作 用户注册,在用户注册页面通过填写账号,密码,确认密码,姓名,手机,所在学校,邮箱,验证码等信息进行注册操作 组织信息,在组织信息页面可以查看组织名称,组织编号,组织宣言,负责人,联系电话等内容,并进行评论和收藏操作 项目关键技术 开发工具:IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7+ 后端技术:ssm 前端技术:Vue 关键技术:springboot、SSM、vue、MYSQL、MAVEN 数据库工具:Navicat、SQLyog
全代码在里面,学完Java实训写出来的Java图书馆代码
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。