简单设计模式——观察者模式

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

观察者模式简介

观察者模式(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,执行相应的方法。这样如果监听者特别多,那么就损失效率。

最后

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

posted @ 2020-04-16 12:24  BobCheng  阅读(130)  评论(0编辑  收藏  举报