/注:场景和例子引用github上的设计模式。传送门:https://github.com/iluwatar/java-design-patterns/tree/master/observer

场景:

一个天气预报系统,凡是订阅了改天气预报的,当天气发生改变的时候就把通知发送给所有订阅该天气预报的人。如兽人族(Orcs)和霍比特人(Hobitts)订阅了该天气预报系统,当天气从晴变成雨天的时候,兽人族和霍比特人就收到了天气变成雨天的通知。 如果还有其他订阅了该天气预报的如人族(Terran),只需要在WeatherObserver中加入该人族(Terran)订阅者,这样当天气发生改变的时候,人族也会收到天气通知。

意图:

定义对象间的一对多关系,当一个对象发生状态更改时,会自动通知并更新所有依赖者。

具体实现:

         订阅天气预报系统的即是观察者(如Orcs、Hobitts),把这些订阅天气预报的人抽象成接口(WeatherObserver),所有订阅该天气预报的人都得实现这个接口才行。另外在天气类(Weather)中也得开放一个接口让他们订阅,如使用List<Subscriber> observers 和写一个方法 addObserver(WeatherObserver obs)来让他们订阅,一旦天气发生变化就通知所有订阅该天气的方法 notifyAllObserver()。

talk is cheap,show me the code............................................................................................................................................................................................................................................................(分割线)

先定义天气类型(WeatherType.java),定义为枚举类型(sunny,rainny,windy,clod)

  1. public enum WeatherType {
  2. SUNNY,WINDY,CLOD,RAINY;
  3.  
  4. @Override
  5. public String toString(){
  6. return this.name().toLowerCase();
  7. }
  8. }

再将订阅者抽象成一个接口(WeatherObserver.java),所有订阅天气预报系统的必须实现这个接口。

  1. public interface WeatherObserver {
  2. public void Upadate(WeatherType currentWeather);
  3. }

天气类(Weather)负责定义数据结构来接收订阅者和通知更新订阅者天气变化。使用List<WeatherObserver>来接收订阅者,定义方法addObserver来接收新的订阅者和notifyAllObsever方法来更新订阅者天气状态。

  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. public class Weather {
  5. private WeatherType currentWeather;
  6. private List<WeatherObserver> observers;
  7.  
  8. public Weather(){
  9. observers=new ArrayList<>();
  10. currentWeather=WeatherType.SUNNY;
  11. }
  12.  
  13. public void addObservers(WeatherObserver observer){
  14. observers.add(observer);
  15. }
  16.  
  17. public void removeObservers(WeatherObserver observer){
  18. observers.remove(observer);
  19. }
  20.  
  21. public void timePasses(){
  22. WeatherType[] enumValues=WeatherType.values();
  23. /* for(WeatherType type:enumValues){
  24. System.out.println(type);
  25. }*/
  26. //改变天气,让天气的enum类型往后推一个
  27. currentWeather=enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
  28. System.out.println("The weather change to "+currentWeather);
  29. notifyAllObserver();
  30. }
  31.  
  32. public void notifyAllObserver(){
  33. for(WeatherObserver obs: observers){
  34. obs.Upadate(currentWeather);
  35. }
  36. }
  37. }

添加两个订阅天气预报的“人”,一个兽族(Orcs.java)一个霍比特人(Hobitts.java)。 如上面所说,要订阅该天气预报必须实现WeatherOberver接口。

  1. public class Orcs implements WeatherObserver{
  2.  
  3. @Override
  4. public void Upadate(WeatherType currentWeather) {
  5. switch(currentWeather){
  6. case CLOD:
  7. System.out.println("The orcs are freezing cold");
  8. break;
  9. case SUNNY:
  10. System.out.println("The sun hurts the orcs' eyes.");
  11. break;
  12. case RAINY:
  13. System.out.println("The orcs are dripping wet.");
  14. break;
  15. case WINDY:
  16. System.out.println("The orc smell almost vanishes in the wind.");
  17. default:
  18. break;
  19. }
  20. }
  21.  
  22. public class Hobbits implements WeatherObserver{
  23.  
  24. @Override
  25. public void Upadate(WeatherType currentWeather) {
  26. switch(currentWeather){
  27. case CLOD:
  28. System.out.println("The Hobbits are freezing cold");
  29. break;
  30. case SUNNY:
  31. System.out.println("The sun hurts the Hobbits' eyes.");
  32. break;
  33. case RAINY:
  34. System.out.println("The Hobbits are dripping wet.");
  35. break;
  36. case WINDY:
  37. System.out.println("The Hobbits smell almost vanishes in the wind.");
  38. default:
  39. break;
  40. }
  41. }
  42. }

写一个主类来测试一下改功能(App.java)

  1. public class APP {
  2. public static void main(String[] args){
  3. Weather weather=new Weather();
  4. weather.addObservers(new Orcs());
  5. weather.addObservers(new Hobbits());
  6.  
  7. //weather.addObservers(new Terran());
  8.  
  9. weather.timePasses();
  10.  
  11. //weather.timePasses();
  12.  
  13. }
  14. }

输出:(即天气从Sunny变成Windy的时候,订阅该天气的Orcs和Hobitts都收到了天气改变的通知)

  1. The weather change to windy
  2. The orc smell almost vanishes in the wind.
  3. The Hobbits smell almost vanishes in the wind.

在以下任何情况下使用观察者模式:

  • 抽象有两个方面,一个依赖于另一个。将这些方面封装在单独的对象中可以让您独立地更改和重用它们
  • 当更改一个对象需要更改其他对象时,您不知道需要更改多少个对象
  • 当一个对象应该能够通知其他对象,而不需要假设这些对象是谁。换句话说,你不希望这些对象紧密结合

观察者模式/ java实现附代码 /的更多相关文章

  1. 单例模式/ java实现附代码 /

    注: 场景和例子出自github的设计模式.传送门:https://github.com/iluwatar/java-design-patterns/tree/master/singleton 意图: ...

  2. 正则表达式学习笔记(附:Java版示例代码)

    具体学习推荐:正则表达式30分钟入门教程 .         除换行符以外的任意字符\w      word,正常字符,可以当做变量名的,字母.数字.下划线.汉字\s        space,空白符 ...

  3. SpringCloud-创建服务消费者-Feign方式(附代码下载)

    场景 SpringCloud-服务注册与实现-Eureka创建服务注册中心(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  4. JPA中实现双向多对多的关联关系(附代码下载)

    场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...

  5. Dubbo与SpringBoot整合流程(从实例入手,附代码下载)

    场景 Dubbo环境搭建-管理控制台dubbo-admin实现服务监控: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10362 ...

  6. 07.深入浅出 Spring Boot - 数据访问之Mybatis(附代码下载)

    MyBatis 在Spring Boot应用非常广,非常强大的一个半自动的ORM框架. 代码下载:https://github.com/Jackson0714/study-spring-boot.gi ...

  7. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...

  8. 分享5种风格的 jQuery 分页效果【附代码】

    jPaginate 是一款非常精致的分页插件,提供了五种不同风格的分页效果,支持鼠标悬停翻页,快速分页功能.这款插件还提供了丰富的配置选项,你可以根据需要进行设置. 效果演示      源码下载 各个 ...

  9. java俄罗斯方块游戏代码

    java俄罗斯方块游戏代码: package com; import java.awt.Color; import java.awt.Graphics; import java.awt.event.K ...

随机推荐

  1. python标准库介绍——15 fileinput 模块详解

    ``fileinput`` 模块允许你循环一个或多个文本文件的内容, 如 [Example 2-1 #eg-2-1] 所示. ====Example 2-1. 使用 fileinput 模块循环一个文 ...

  2. 为anaconda的jupyter notebook设置初始化目录

    在使用jupyter进行编程时,初始化目录可能不是自己想要的目录,那么下面讲解修改成自己想要的目录. 1) 在命令行中输入jupyter notebook --generate-config,会产生一 ...

  3. 《Effective Java》读书笔记六(方法)

    No38 检查参数的有效性 对于公有的方法,要用Javadoc的@throws标签(tag)在文档中说明违反参数值时会抛出的异常.这样的异常通常为IllegalArgumentException.In ...

  4. Sqlite 常用函数推荐

    Sqlite 常用函数 1 .打开数据库: 说明:打开一个数据库,文件名不一定要存在,如果此文件不存在, sqlite 会自动创建.第一个参数指文件名,第二个参数则是定义的 sqlite3 ** 结构 ...

  5. Spring 一二事(7) - annotation

    之前的文章大多都是一带而过,一方面比较简单,一方面不是用的注解形式 在企业开发中,主要还是使用的注解来进行开发的 1 <!-- component:把一个类放入到spring容器中,该类就是一个 ...

  6. FPGA按键去抖verilog代码

    按键去抖的原因及其分类就不罗嗦了. 在这里解释一段代码,代码是网上找的,看了半天没懂,无奈查了半天想了半天,终于明白了... module sw_debounce(clk,rst_n,sw1,sw2, ...

  7. Linux 监控分析

    一.硬件基础 Cpu   逻辑的处理.计算.判断 现代分时多任务操作系统对 CPU 都是分时间片使用的:比如A进程占用10ms,然后B进程占用30ms,然后空闲60ms, 再又是A进程占10ms,B进 ...

  8. python学习之base64模块

    常见方法: base64.encodebytes() 参数: 接收一个字节对象. 返回值: 返回base64编码的数据(以'\n'结尾的数据). base64.decodebytes() 参数: 接收 ...

  9. CTreeCtrl 父结点联动子结点CheckBox

    实现很简单,直接上代码: void CCheckBoxTreeDlg::OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult) { // TODO: 在此添加控 ...

  10. Win7网络修复,winsock/tcpip

    1.win7自带网络诊断提示没有安装一个或多个协议,ip地址为169.254.x.x,dns地址为空 2.修复winsock时,提示系统找不到指定的文件. 解决办法: 1. netsh int ip ...