zoukankan      html  css  js  c++  java
  • 简单设计模式——观察者模式

    设计模式其实不难,难得是根据实际情况使用合适的设计模式来实现业务逻辑。

    观察者模式简介

    观察者模式(Observer Pattern)是处理一对多关系的时候可以使用观察者模式。比如:一个A对象被修改,有一些依赖他的对象会观察到A被修改了,这些依赖A的对象就被称为观察者,而对象A就是被观察者。

    主要使用的类

    1. Observer:观察者接口(或者是抽象类),用来规范观察者需要实现哪些方法。
    2. ObServer的实现类:用来具体实现观察者。
    3. Subject:主体接口(或者是抽象类),用于规范主体需要实现那些方法。这里面的主体也就是被观察者。
    4. Subject的实现类:用于根据需求实现主体类。

    举个例子

    假如有个开发天气预报软件的公司,他们现在需要实现一个功能。他们有一个天气的数据中心,里面会实时根据当前天气情况更新数据。现在需要实现每次数据更新的时候,他们的web网站应用、安卓手机上的app、IOS手机上的app都会更新数据。

    分析

    在这个例子中:我们的web应用、安卓手机上的app、IOS手机上的app都是一个个观察者。而天气的数据中心就是一个被观察者。

    实现

    1. 首先实现我们的观察者接口:Observer
    public interface Observer {
        //weatherMsg是天气信息
        void update(String weatherMsg);
    }
    

    在此例子中,无论是web还是app更新,都是需要提供一个天气的数据的。所以更新方法需要一个形参代表天气信息的数据。

    1. 实现web的监听者:WebObserver
    public class WebObserver implements Observer {
        @Override
        public void update(String weatherMsg) {
            System.out.println("更新Web应用的天气数据=>"+weatherMsg);
        }
    }
    
    1. 实现安卓app的监听者:AndroidObserver
    public class AndroidObserver implements Observer {
        @Override
        public void update(String weatherMsg) {
            System.out.println("更新安卓APP上的天气数据=>"+weatherMsg);
        }
    }
    
    1. 实现IOSapp的监听者:IosObserver
    public class IosObserver implements Observer{
        @Override
        public void update(String weatherMsg) {
            System.out.println("更新苹果APP上的天气数据=>"+weatherMsg);
        }
    }
    
    1. 监听者都实现了,下下面实现被监听者(也就是主体)接口:Subject
    public interface Subject {
        //添加一个观察者,告诉被观察者有个对象在观察你。
        boolean register(Observer observer);
        //移除一个观察者,告诉被观察者此对象不再观察你了。
        boolean remove(Observer observer);
        //通知所有观察者,状态改变了。
        void notifyAllObserver();
    }
    
    1. 实现被观察者,也就是例子中的天气数据中心。
    public class WeatherDataCenterSubject implements Subject {
        //一个list对象,用于储存哪些对象观察了此对象。
        private List<Observer> observers=new ArrayList<>();
    
        //因为是小的案例,所以这里没有处理线程,真正开发中肯定不能这样写的。要根据实际情况来。
        private String weatherMsg="";
    
        public WeatherDataCenterSubject(String currentWeather){
            this.weatherMsg=currentWeather;
            System.out.println("当前天气 => "+currentWeather);
        }
        
        //数据中心的天气数据更新
        public void updateData(String weather){
            System.out.println("天气更新 => "+weather);
            //调用通知方法,通知所有观察者数据中心的数据更新了
            this.notifyAllObserver();
        }
    
        @Override
        public boolean register(Observer observer) {
            return observers.add(observer);
        }
    
        @Override
        public boolean remove(Observer observer) {
            return observers.remove(observer);
        }
    
        @Override
        public void notifyAllObserver() {
            for(Observer item : observers){
                item.update(weatherMsg);
            }
        }
    }
    
    1. 测试
    public class Test {
        public static void main(String[] args) {
            WeatherDataCenterSubject weatherDataCenter=new WeatherDataCenterSubject("晴,17摄氏度,空气质量优");
            weatherDataCenter.register(new WebObserver());
            weatherDataCenter.register(new AndroidObserver());
            weatherDataCenter.register(new IosObserver());
            System.out.println("======================");
            weatherDataCenter.updateData("阴天,16摄氏度,空气质量中");
            System.out.println("======================");
            weatherDataCenter.updateData("小雨,13摄氏度,空气质量优");
        }
    }
    

    输出结果:

    当前天气 => 晴,17摄氏度,空气质量优
    ======================
    天气更新 => 阴天,16摄氏度,空气质量中
    更新Web应用的天气数据=>晴,17摄氏度,空气质量优
    更新安卓APP上的天气数据=>晴,17摄氏度,空气质量优
    更新苹果APP上的天气数据=>晴,17摄氏度,空气质量优
    ======================
    天气更新 => 小雨,13摄氏度,空气质量优
    更新Web应用的天气数据=>晴,17摄氏度,空气质量优
    更新安卓APP上的天气数据=>晴,17摄氏度,空气质量优
    更新苹果APP上的天气数据=>晴,17摄氏度,空气质量优
    

    如何拓展?

    如果这时候又开发个TV版的天气预报软件,就只需要实现一个TVObserver,然后注册到数据中心就好。如:weatherDataCenter.register(new TVObserver());

    观察者模式有什么缺点

    上面的例子中,观察者是通过注册方法添加到被观察者的一个list中的。然后每次被观察者数据改变了都会遍历list,执行相应的方法。这样如果监听者特别多,那么就损失效率。

    最后

    从代码上看观察者模式叫通知模式更合适吧?

    作者:BobC

    文章原创。如你发现错误,欢迎指正,在这里先谢过了。博主的所有的文章、笔记都会在优化并整理后发布在个人公众号上,如果我的笔记对你有一定的用处的话,欢迎关注一下,我会提供更多优质的笔记的。
  • 相关阅读:
    EJB>Session Beans
    JSF>标准转换器(Converter)
    EJB>定时服务(Timer Service)
    EJB>实体继承
    EJB>拦截器(Interceptor)
    JSF>输入、输出、命令、选择、表格、其他标签
    JBoss的配置
    JSF>JSF 生命周期
    EJB>改变sessionbean的JNDI名称
    JSF>错误讯息处理
  • 原文地址:https://www.cnblogs.com/Eastry/p/12711668.html
Copyright © 2011-2022 走看看