zoukankan      html  css  js  c++  java
  • Java基础知识之设计模式--观察者模式

    Java设计模式--观察者模式

    声明:本文根据慕课网GerryZhang老师的精品课程整理来的:慕课网

     什么是设计模式(Design Pattern)?

      设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。

    观察者模式的定义?

      定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知,并被自动更新。

    观察者模式的分类?

      1.推模型:目标对象主动向观察者推送目标的详细信息,推送的信息通常是目标对象的全部或部分数据,相当于广播通信

      2.拉模型:目标对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。一般这种模型的实现中,会把目标对象自身通过update方法传递给观察者。

    Java中提供的观察者实现与自己实现的对比:

      1.不需要再定义观察者和目标的接口了,JDK帮忙定义了

      2.具体的目标实现里面不需要再维护观察者的注册信息了,这个在Java中的Observable类里面已经帮忙实现了。

      3.触发通知的方式有一些变化,要先调用setChanged方法,这个是Java为了帮助实现更精确的触发控制而提供的功能。

      4.具体观察者的实现里面,update方法其实能同时支持推模型和拉模型,这个是Java在定义的时候,就已经考虑进去了。

    观察者模式的优点和缺点:

      优点:

        1.观察者模式实现了观察者和目标之间的抽象耦合。

        2.观察者模式实现了动态联动。

        3.观察者模式支持广播通信。

      缺点:

        可能会引起无谓的操作

    在什么情况下使用观察者模式:

      1.当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化。

      2.如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变。

      3.当一个对象必须通知其他的对象,但你又希望这个对象和其他被通知的对象是松散耦合的。

    推模型示例:

      1.创建观察者接口和目标对象

     /**
      * 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变时被通知的对象
      * @author Administrator
      *
      */
     public interface Observer {
         /**
          * 更新的接口
          * @Description: TODO
          * @param subject
          * @returnType: void
          */
         public void update(WeatherSubject subject);
     }
    /**
      * 目标对象,它知道观察它的观察者,并提供注册(添加)和删除观察者的接口。
      * @author Administrator
      *
      */
     public class WeatherSubject {
         // 用来保存注册的观察者对象
         List<Observer> observers = new ArrayList<Observer>();
     
         /**
          * 把订阅的人添加到订阅者列表中
          */
         public void attach(Observer observer) {
             observers.add(observer);
         }
     
         /**
          * 从集合中删除观察者
          */
         public void detach(Observer observer) {
             if (observers.contains(observer)) {
                 observers.remove(observer);
             }
         }
     
         /**
          * 通知所有注册的观察者对象
          */
         protected void notifyObservers() {
             for (Observer observer : observers) {
                 observer.update(this);
             }
         }
     }

      2.分别创建具体的目标对象和具体的观察者对象

     /**
       * 具体的目标对象,负责把有关状态存入到相应的观察者对象中
       * @author Administrator
       *
       */
      public class ConcreteWeatherSubject extends WeatherSubject {
          //获取天气的内容信息
          private String weatherContent;
      
          /**
           * @return the weatherContent
           */
          public String getWeatherContent() {
              return weatherContent;
          }
      
          /**
           * @param weatherContent the weatherContent to set
           */
          public void setWeatherContent(String weatherContent) {
              this.weatherContent = weatherContent;
              //内容有了,说明天气更细了,通知所有的订阅人
              this.notifyObservers();
          }  
      }
     /**
      * 具体的观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
       * @author Administrator
       *
      */
     public class ConcreteObserver implements Observer {
          //观察者的名字,是谁收到了这个信息
          private String observerName;
          
         //天气内容的情况,这个消息从目标处获取
         private String weatherContent;
         
         //提醒的内容,根据不同的人提醒不同的信息
         private String remindThing;
         
         /**
          * 获取目标类的状态同步到观察者的状态中
          */
         @Override
         public void update(WeatherSubject subject) {
             weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
             System.out.println(observerName+"收到了"+weatherContent+","+remindThing);
         }
     
         /**
          * @return the observerName
          */
         public String getObserverName() {
             return observerName;
         }
     
         /**
          * @param observerName the observerName to set
          */
         public void setObserverName(String observerName) {
             this.observerName = observerName;
         }
     
         /**
          * @return the weatherContent
          */
         public String getWeatherContent() {
             return weatherContent;
         }
     
         /**
          * @param weatherContent the weatherContent to set
          */
         public void setWeatherContent(String weatherContent) {
             this.weatherContent = weatherContent;
         }
     
         /**
          * @return the remindThing
          */
         public String getRemindThing() {
             return remindThing;
         }
     
         /**
          * @param remindThing the remindThing to set
          */
         public void setRemindThing(String remindThing) {
             this.remindThing = remindThing;
         } 
    }

      3.创建测试类进行测试

      程序运行逻辑(准备阶段):

        1.创建目标对象

        2.创建观察者对象

        3.向目标对象注册观察者对象

      程序性运行逻辑(运行阶段):

        1.改变目标对象的状态

        2.目标对象通知所有观察者对象运行相应的处理

        3.观察者对象回调目标对象,获取相应的数据

     public class Test {
      
          public static void main(String[] args) {
              //1.创建一个目标
              ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
              
              //2.创建一个观察者
              ConcreteObserver girlObserver = new ConcreteObserver();
              girlObserver.setObserverName("黄明的女朋友");
             girlObserver.setRemindThing("天气很好,适合约会");
             
             ConcreteObserver mumObserver = new ConcreteObserver();
             mumObserver.setObserverName("黄明的老妈");
             mumObserver.setRemindThing("天气很好,适合购物");
             
             //3.注册观察者
             subject.attach(girlObserver);;
             subject.attach(mumObserver);
             
             //4.目标发布天气
             subject.setWeatherContent("明天天气晴朗,气温28度");
         }
     
     }

    拉模型示例:

      1.创建观察者接口和目标对象

     /**
       * 这是一个观察者接口,定义一个更新的接口给那些在目标发生改变时被通知的对象
       * @author Administrator
       *
       */
      public interface Observer {
          /**
           * 更新的接口
           * @Description: TODO
          * @param subject
          * @returnType: void
          */
         public void update(String content);
     }
     /**
       * 目标对象,它知道观察它的观察者,并提供注册(添加)和删除观察者的接口。
       * @author Administrator
       *
       */
      public class WeatherSubject {
          // 用来保存注册的观察者对象
          List<Observer> observers = new ArrayList<Observer>();
      
         /**
          * 把订阅的人添加到订阅者列表中
          */
         public void attach(Observer observer) {
             observers.add(observer);
         }
     
         /**
          * 从集合中删除观察者
          */
         public void detach(Observer observer) {
             if (observers.contains(observer)) {
                 observers.remove(observer);
             }
         }
     
         /**
          * 通知所有注册的观察者对象
          */
         protected void notifyObservers(String content) {
             for (Observer observer : observers) {
                 observer.update(content);
             }
         }
     } 

      2.分别创建具体的目标对象和具体的观察者对象

     /**
       * 具体的目标对象,负责把有关状态存入到相应的观察者对象中
       * @author Administrator
       *
       */
      public class ConcreteWeatherSubject extends WeatherSubject {
          //获取天气的内容信息
          private String weatherContent;
      
         /**
          * @return the weatherContent
          */
         public String getWeatherContent() {
             return weatherContent;
         }
     
         /**
          * @param weatherContent the weatherContent to set
          */
         public void setWeatherContent(String weatherContent) {
             this.weatherContent = weatherContent;
             //内容有了,说明天气更细了,通知所有的订阅人
             this.notifyObservers(weatherContent);
         } 
     }
     /**
       * 具体的观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
       * @author Administrator
       *
       */
      public class ConcreteObserver implements Observer {
          //观察者的名字,是谁收到了这个信息
          private String observerName;
          
         //天气内容的情况,这个消息从目标处获取
         private String weatherContent;
         
         //提醒的内容,根据不同的人提醒不同的信息
         private String remindThing;
         
         /**
          * 获取目标类的状态同步到观察者的状态中
          */
         @Override
         public void update(String content) {
             weatherContent = content;
             System.out.println(observerName+"收到了"+weatherContent+","+remindThing);
         }
     
         /**
          * @return the observerName
          */
         public String getObserverName() {
             return observerName;
         }
     
         /**
          * @param observerName the observerName to set
          */
         public void setObserverName(String observerName) {
             this.observerName = observerName;
         }
     
         /**
          * @return the weatherContent
          */
         public String getWeatherContent() {
             return weatherContent;
         }
     
         /**
          * @param weatherContent the weatherContent to set
          */
         public void setWeatherContent(String weatherContent) {
             this.weatherContent = weatherContent;
         }
     
         /**
          * @return the remindThing
          */
         public String getRemindThing() {
             return remindThing;
         }
     
         /**
          * @param remindThing the remindThing to set
          */
         public void setRemindThing(String remindThing) {
             this.remindThing = remindThing;
         }   
     }

      3.创建测试类进行测试

     public class Test {
          public static void main(String[] args) {
              // 1.创建一个目标
              ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
      
              // 2.创建一个观察者
              ConcreteObserver girlObserver = new ConcreteObserver();
              girlObserver.setObserverName("黄明的女朋友");
              girlObserver.setRemindThing("天气很好,适合约会");
     
             ConcreteObserver mumObserver = new ConcreteObserver();
             mumObserver.setObserverName("黄明的老妈");
             mumObserver.setRemindThing("天气很好,适合购物");
     
             // 3.注册观察者
             subject.attach(girlObserver);
             ;
             subject.attach(mumObserver);
     
             // 4.目标发布天气
             subject.setWeatherContent("明天天气晴朗,气温28度");
         }
     }

    使用Java提供的观察者实现进行实例测试:

      1.创建目标的具体实现类,继承于Java提供的Observable类

     /**
       * 天气目标的具体实现类
       * @author Administrator
       *
       */
      public class ConcreteWeatherSubject extends Observable {
          //天气情况的内容
          private String content;
      
         public String getContent() {
             return content;
         }
         
         public void setContent(String content) {
             this.content = content;
             //天气情况有了,就要通知所有的观察者
             //注意在通知之前,在用Java中的Observer模式的时候,下面这句话不可少
             this.setChanged();
             //然后主动通知,这里用推的模式实现
             this.notifyObservers(content);
             //如果是拉的模式实现,使用不带参数的
             //this.notifyObservers();
         }
     }

      2.创建具体的观察者对象,实现Java提供的Observer接口

     /**
       * 具体的观察者对象
       * @author Administrator
       *
       */
      public class ConcreteObserver implements Observer {
      
          //观察者名称的变量
          private String observerName;
         @Override
         public void update(Observable o, Object arg) {
             //第一种是推的方式
             System.out.println(observerName+"收到了消息,目标推送过来的是:"+arg);
             //第二种是拉的方式
             System.out.println(observerName+"收到了消息,主动到目标对象中去拉,拉的内容是"
                     +((ConcreteWeatherSubject)o).getContent());
         }
         public String getObserverName() {
             return observerName;
         }
         public void setObserverName(String observerName) {
             this.observerName = observerName;
         }
     }

      3.测试类

     /**
       * 测试类
       * @author Administrator
       *
       */
      public class Test {
          public static void main(String[] args) {
              //创建天气作为一个目标,也可以说是被观察者
              ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
             //创建黄明的女朋友作为观察者
             ConcreteObserver girlObserver = new ConcreteObserver();
             girlObserver.setObserverName("黄明的女朋友");
             //创建黄明的老妈作为观察者
             ConcreteObserver mumObserver = new ConcreteObserver();
             mumObserver.setObserverName("黄明的老妈");
             
             //注册观察者
             subject.addObserver(mumObserver);
             subject.addObserver(girlObserver);
             
             //目标更新天气情况
             subject.setContent("天气晴,气温28度");
         }
     }
  • 相关阅读:
    [转]Object Tracking using OpenCV (C++/Python)(使用OpenCV进行目标跟踪)
    [转]PIL、Pillow安装使用方法
    [转]痞子衡嵌入式:飞思卡尔Kinetis开发板OpenSDA调试器那些事(上)
    如何选择开源许可证?
    年复一年
    [转]TLD目标跟踪算法
    [转]pycharm中将ui文件转换成py文件
    ps矫正倾斜的扫描件内容
    ORM增删改查
    ORM配置
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/12319432.html
Copyright © 2011-2022 走看看