zoukankan      html  css  js  c++  java
  • 观察者模式/ java实现附代码 /

     /注:场景和例子引用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)

    public enum WeatherType {
         SUNNY,WINDY,CLOD,RAINY;
    	 
    	 @Override
    	 public String toString(){
    		 return this.name().toLowerCase();
    	 }
    }
    

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

    public interface WeatherObserver {
          public void Upadate(WeatherType currentWeather);
    }

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

    import java.util.ArrayList;
    import java.util.List;
    
    public class Weather {
         private WeatherType currentWeather;
         private List<WeatherObserver> observers;
         
         public Weather(){
             observers=new ArrayList<>();
             currentWeather=WeatherType.SUNNY;
         }
         
         public void addObservers(WeatherObserver observer){
             observers.add(observer);
         }
         
         public void removeObservers(WeatherObserver observer){
             observers.remove(observer);
         }
         
         
         public  void timePasses(){
             WeatherType[] enumValues=WeatherType.values();
            /* for(WeatherType type:enumValues){
                 System.out.println(type);
             }*/
             //改变天气,让天气的enum类型往后推一个
             currentWeather=enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
             System.out.println("The weather change to  "+currentWeather);
             notifyAllObserver();
         }
         
         public void notifyAllObserver(){
             for(WeatherObserver obs: observers){
                 obs.Upadate(currentWeather);
             }
         }
    }

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

    public class Orcs implements WeatherObserver{
    
        @Override
        public void Upadate(WeatherType currentWeather) {
            switch(currentWeather){
            case CLOD:
                System.out.println("The orcs are freezing cold");
                break;
            case SUNNY:
                System.out.println("The sun hurts the orcs' eyes.");
                break;
            case RAINY:
                System.out.println("The orcs are dripping wet.");
                break;
            case WINDY:
                System.out.println("The orc smell almost vanishes in the wind.");
            default:
                break;
            }        
        }
    
    
    public class Hobbits implements WeatherObserver{
    
        @Override
        public void Upadate(WeatherType currentWeather) {
            switch(currentWeather){
            case CLOD:
                System.out.println("The Hobbits are freezing cold");
                break;
            case SUNNY:
                System.out.println("The sun hurts the Hobbits' eyes.");
                break;
            case RAINY:
                System.out.println("The Hobbits are dripping wet.");
                break;
            case WINDY:
                System.out.println("The Hobbits smell almost vanishes in the wind.");
            default:
                break;
            }       
        }
    }

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

    public class APP {
        public static void main(String[] args){
            Weather weather=new Weather();
            weather.addObservers(new Orcs());
            weather.addObservers(new Hobbits());
            
            //weather.addObservers(new Terran());
            
            weather.timePasses();
            
            //weather.timePasses();
            
        }
    }

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

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

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

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

     

    余虽不敏,然余诚矣。如果有什么不对的地方望不吝赐教,希望通过博客来沉淀自己和分享讨论自己的见解。
  • 相关阅读:
    caffe的python接口学习(5):生成deploy文件
    Flutter -------- 新手 WanAndroid 项目练习
    android -------- GifView 显示gif图片
    android -------- java.net.UnknownServiceException
    Flutter ------- WebView加载网页
    Flutter -------- 解析JSON数据
    Flutter -------- Http库 网络请求封装(HttpController)
    android ------ 实现高德定位并获取相应信息 ( 最新版高德SDK 和 Android SDK版本)
    Flutter -------- dio网络请求
    Flutter -------- Http库实现网络请求
  • 原文地址:https://www.cnblogs.com/ahangBlogs/p/7988561.html
Copyright © 2011-2022 走看看