zoukankan      html  css  js  c++  java
  • (java)从零开始之--观察者设计模式Observer

    观察者设计模式:时当一个对象发生指定的动作时,要通过另外的对象做出相应的处理。

    步骤:
    1. A对象发生指定的动作是,要通知B,C,D...对象做出相应的处理,这时候应该把B,C,D...对象针对A对象的动作做出的相应处理方法定义在接口上(这是一种规范,凡事需要A对象通知的对象,都要实现该接口)。
    2. 在A对象维护接口的引用,当A对象发生指定的动作这时候即可调用接口中的方法。

    观察者模式的应用场景:

    1. 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

    2.对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

    假设有一个例子:

    气象台每天都会更新天气预报,订阅的人群都可以在每次气象台发布天气预报,都可以接收到天气预报信息.订阅人群可以根据天气预报信息做出相应处理

    被观察对象(Subject)

     1 /*
     2  * 气象台类
     3  * 
     4  */
     5 public class WeatherStation {
     6 
     7     private String[] weatherArr = {"大雨","大雪","台风","雾霾","多云","晴"};
     8     private String weatherDesc = weatherArr[0];
     9     private ArrayList<IWeather> list = new ArrayList<IWeather>();
    10     
    11     //对外提供一个方法添加天气预报更新时,要通知的对象
    12     public void add(IWeather weather){
    13         this.list.add(weather);
    14     }
    15     
    16     //对外提供一个方法取消订阅天气预报
    17     public void remove(IWeather weather){
    18         if(weatherArr.length>0){
    19             for (int i = 0; i < weatherArr.length; i++) {
    20                 if(list.get(i).equals(weather)){
    21                     this.list.remove(i);
    22                     break;
    23                 }
    24             }
    25             
    26         }
    27     }
    28     
    29     
    30     //开始天气预报
    31     public void startWeatherForecast(){
    32         new Thread(){
    33             @Override
    34             public void run() {
    35                 while(true){
    36                     updateWeather();//每3秒钟更新一次天气预报 (模拟每天气象台自动更新天气预报)
    37                     for (IWeather weather : list) {
    38                         weather.updateWeather(weatherDesc);
    39                     }
    40                     try {
    41                         Thread.sleep(3000);
    42                     } catch (InterruptedException e) {
    43                         e.printStackTrace();
    44                     }
    45                     
    46                 }
    47             }
    48         }.start();
    49         
    50     }
    51     
    52     
    53     //气象台更新天气
    54     public void updateWeather(){
    55         Random random = new Random();
    56         int n = random.nextInt(weatherArr.length);
    57         this.weatherDesc = weatherArr[n];
    58         System.out.println("气象台发布天气预报:"+this.weatherDesc);
    59     }
    60     
    61 }

    所有订阅的群体必须具有一个共同updateWeather的方法(实现该接口),这样气象台发布新天气预报时候,即可通过调用订阅对象执行该方法,达到通知目的。

    /*
     * 一个接口规范,实现了该接口对象所要做的动作。
     * 实现该接口的对象当气象台天气预报更新时执行
     * {"大雨","大雪","台风","雾霾","多云","晴"}
     */
    public interface IWeather {
        public void updateWeather(String weatherDesc);
    }

    订阅的群体类 观察者对象Observer

     1 /*
     2  * 可能订阅群个之一,工作者
     3  * 
     4  */
     5 public class Emp implements IWeather {
     6 
     7     String name;
     8     int age;
     9     
    10     public Emp(String name, int age) {
    11         this.name = name;
    12         this.age = age;
    13     }
    14 
    15     //{"大雨","大雪","台风","雾霾","多云","晴"}
    16     @Override
    17     public void updateWeather(String weatherDesc) {
    18         System.out.println(this.name+":收到天气预报 "+weatherDesc);
    19     }
    20 }

    -

    /*
     * 可能订阅群体之一, 学生
     */
    public class Student implements IWeather {
    
        String name;
        int age;
        
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        //{"大雨","大雪","台风","雾霾","多云","晴"}
        @Override
        public void updateWeather(String weatherDesc) {
            System.out.println(this.name+":收到天气预报 "+weatherDesc);
        }
    
    }

    Main、

     1 public class WeatherMain {
     2 
     3     public static void main(String[] args) {
     4         WeatherStation weatherStation = new WeatherStation();
     5 
     6         Student s1 = new Student("小明", 10);
     7         Student s2 = new Student("小美", 10);
     8         Emp e1 = new Emp("大明", 10);
     9         Emp e2 = new Emp("大美", 10);
    10         weatherStation.add(s1);
    11         weatherStation.add(s2);
    12         weatherStation.add(e1);
    13         weatherStation.add(e2);
    14         weatherStation.remove(e2);
    15         weatherStation.startWeatherForecast();
    16     }
    17 
    18 }

    因为“大美”取消了天气预报,所以没有收到天气预报通知

    执行结果:

    气象台发布天气预报:大雪
    小明:收到天气预报 大雪
    小美:收到天气预报 大雪
    大明:收到天气预报 大雪
    气象台发布天气预报:雾霾
    小明:收到天气预报 雾霾
    小美:收到天气预报 雾霾
    大明:收到天气预报 雾霾
    气象台发布天气预报:台风
    小明:收到天气预报 台风
    小美:收到天气预报 台风
    大明:收到天气预报 台风
    气象台发布天气预报:晴
    小明:收到天气预报 晴
    小美:收到天气预报 晴
    大明:收到天气预报 晴
    气象台发布天气预报:雾霾
    小明:收到天气预报 雾霾
    小美:收到天气预报 雾霾
    大明:收到天气预报 雾霾

    ...

  • 相关阅读:
    Homework template (latex)
    Basic skill of searching
    国庆第三次集训: 2012 ACM-ICPC Asia Regional Contest Chengdu Site
    新学期随笔
    暑期集训感想
    暑期集训 DP 篇
    POJ 1195 Mobile Phones 二维树状数组
    51Nod1246 罐子和硬币,不能均分的题
    一维战舰,一道考区间的好题
    51NOD 1268 和为K的组合 搜索水题
  • 原文地址:https://www.cnblogs.com/fnz0/p/5476017.html
Copyright © 2011-2022 走看看