23种设计模式之观察者模式

2018/08/19

观察者模式提供了一种对象设计,让被观察者和观察者之间松耦合,降低对象之间的相互依赖。

前言

最近在看Head First 设计模式,了解下观察者模式。书本上实现比较麻烦点,写个简单的。

  • 观察者持有主题的引用,耦合比较紧密。
  • 对于观察者列表,没考虑并发

观察者模式简单实现

类图

代码实现

主题接口

主题实现

public class WeatherSubject implements Subject {
    private Set<Observer> observers;
    //天气状态
    private String state;

    public WeatherSubject() {
        this.observers = new HashSet<>();
    }

    public void notice() {
        System.out.println("获取到最新天气状态");
        System.out.println("状态更新了,开始通知观察者。。。");
        //    通知观察者
        for (Observer observer : observers) {
            observer.update("最新天气信息:" + state);
        }
    }

    @Override
    public void register(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void delete(Observer observer) {
        observers.remove(observer);
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

观察者

public interface Observer {
    void update(String content);
}

观察者实现

public class ObserverBJ implements Observer {
    @Override
    public void update(String content) {
        System.out.println("北京观察站收到更新消息:" + content);
    }
}

public class ObserverSH implements Observer {
    @Override
    public void update(String content) {
        System.out.println("上海观察站收到更新消息:"+content);
    }
}

测试

public class ObServerTest {
    public static void main(String[] args) {
        Subject weather = new WeatherSubject();
        System.out.println("上海站注册天气主题");
        Observer sh=new ObserverSH();
        weather.register(sh);

        System.out.println("北京站注册天气主题");
        Observer bj=new ObserverBJ();
        weather.register(bj);

        System.out.println("天气信息更新");
        ((WeatherSubject) weather).setState("温度29度,湿度30");
        weather.notice();
    }
}

JDK内置观察者模式

类图

实现

继承Observable,直接实现

public class WeatherData extends Observable {
    //天气状态
    private String state;

    @Override
    protected synchronized void setChanged() {
        super.setChanged();
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
        System.out.println("接受到天气信息更新。。。:"+state);
        super.setChanged();
        System.out.println("天气信息更新了,通知观察者。。。");
        super.notifyObservers(state);
    }
}

实现观察者

public class ObserverNJ implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("南京站 最新天气信息: " + arg);
    }
}

public class ObserverHZ implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("杭州站 最新天气信息:"+arg);
    }
}

测试

public class JDKObserverTest {
    public static void main(String[] args) {
        Observable weatherData=new WeatherData();

        ObserverHZ hz=new ObserverHZ();
        ObserverNJ nj=new ObserverNJ();
        weatherData.addObserver(hz);
        weatherData.addObserver(nj);

        ((WeatherData) weatherData).setState("温度29度,湿度30\"");
        //((WeatherData) weatherData).setChanged();
        //weatherData.notifyObservers("温度29度,湿度30");
    }
}

内置模式优点

  1. 封装常用操作

  1. 线程安全

内置模式缺点

JDK内置模式也是有些小问题的。

  1. JDK10以后不支持

  1. Observable要使用必须被继承,

    Java不支持多继承,限制了Observable的复用潜力,违反”多组合、少继承”的设计原则

  2. 方法保护

这意味着,要使用setChanged方法,必须继承Observable

可以的话,自己实现观察者模式吧。不过需要解决观察者列表并发修改的问题。

适用场景

观察者模式适用场景

  1. 被观察者的对象有状态,且变更比较频繁
  2. 被观察者需要持有观察者列表。
  3. 能够通知观察者
  4. 具体的观察者实现统一接口

观察者模式,封装了变化,在对象之间定义一对多的依赖,当一个对象状态改变时,依赖他的对象都会收到通知,并自动更新。


作者:Wuxinshui
出处:http://wuxinshui.github.io
版权归作者所有,转载请注明出处

Post Directory