大话设计模式——观察者模式(一)

来源:互联网 发布:骂人软件 编辑:程序博客网 时间:2024/06/08 04:24

一、概念

1.1 定义

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

1.2 实例场景

小陈在气象局工作,可以为他的家人提供最新的天气情况。这时,小陈就是被观察者,他的家人就是观察者。他的家人订阅天气服务,小陈就可以提供最新的天气预报到订阅者手中。而他的家人收到通知后,可以做出自己的反应。

二、通用代码

2.1 目标类

这里的目标类对应着实例里的小陈,他知道观察自己的观察者(家人),并提供了注册和删除观察者的接口。

public class Subject {    private ArrayList<Observer> observers = new ArrayList<Observer>();    /**     * 添加     * @param observer 观察者     */    public void attach(Observer observer) {        observers.add(observer);    }    /**     * 删除     * @param observer 观察者     */    public void detach(Observer observer) {        observers.remove(observer);    }    /**     * 向所有注册的观察者发送信息     */    protected void notifyObservers(){        for(Observer observer:observers){            observer.update(this);        }    }}

2.2 具体目标类

这个类就相当于是天气预报的功能,负责把有关的状态存入到相应的观察者对象中。

public class ConcreatSubject extends Subject {    private String subjectState;    public String getSubjectState() {        return subjectState;    }    public void setSubjectState(String subjectState) {        this.subjectState = subjectState;        this.notifyObservers();    }}

2.3 观察者接口

此类为观察者的接口,提供了一个更新的接口,当目标发生改变时,通知相应的观察者

public interface Observer {    /**     * 更新的接口     * @param subject subject 传入目标对象,方便获取目标的状态     */    void update(Subject subject);}

2.4 具体的观察者对象

这个类就相当于实例的小陈的家人,他的家人知道天气变化了之后,会采取不同的策略去改变一些事。

public class ConcreatObserver implements Observer {    //观察者状态    private String observerState;    /**     * 获取目标类的状态,同步到观察者中     */    @Override    public void update(Subject subject) {        observerState = ((ConcreatSubject)subject).getSubjectState();    }}

2.5 总结

这样,我们就可以通过改变ConcreatSubject里的状态值,通过循环来通知每一个注册了的观察者,让他们也做出相应的改变。

三、详细设计

3.1 天气目标类

public class WeatherSubject {    //用来保存注册的观察者对象    private ArrayList<Observer> observers = new ArrayList<Observer>();    /**     * 把订阅天气的人添加到订阅者列表中     * @param observer 观察者     */    public void attach(Observer observer) {        observers.add(observer);    }    /**     * 删除订阅天气的人     * @param observer 观察者     */    public void detach(Observer observer) {        observers.remove(observer);    }    /**     * 通知所有已经订阅了天气的人     */    protected void notifyObservers(){        for(Observer observer:observers){            observer.update(this);        }    }}

3.2 具体天气目标类

相当于天气预报,能更改天气信息,并通知他的家人(被观察者)

public class ConcreatWeatherSubject extends WeatherSubject {    private String weatherContent;    public String getWeatherContent() {        return weatherContent;    }    public void setWeatherContent(String weatherContent) {        this.weatherContent = weatherContent;        //天气更新,通知所有订阅天气的观察者        this.notifyObservers();    }}

3.3 观察者类

相当于他的家人,我们细化了一些细节的信息,如名字,行为等。

public class ConcreatObserver implements Observer {    //观察者名称    private String observerName;    //天气情况    private String weatherContent;    //提醒内容    private String remindThing;    public String getObserverName() {        return observerName;    }    public void setObserverName(String observerName) {        this.observerName = observerName;    }    public String getWeatherContent() {        return weatherContent;    }    public void setWeatherContent(String weatherContent) {        this.weatherContent = weatherContent;    }    public String getRemindThing() {        return remindThing;    }    public void setRemindThing(String remindThing) {        this.remindThing = remindThing;    }    /**     * 获取目标类的状态,同步到观察者中     */    @Override    public void update(WeatherSubject subject) {        weatherContent = ((ConcreatWeatherSubject)subject).getWeatherContent();        System.out.println(observerName+"收到了"+weatherContent+","+remindThing);    }}

这里还可以根据天气情况,判断进行不同的事情。

3.4 测试类

对观察者模式的代码进行一个测试。

public class Client {    public static void main(String[] args) {        //1. 创建一个目标        ConcreatWeatherSubject weatherSubject = new ConcreatWeatherSubject();        //2. 创建一个观察者        ConcreatObserver observerGf = new ConcreatObserver();        observerGf.setObserverName("女票");        observerGf.setRemindThing("是我们的第一次约会,地点公园");        ConcreatObserver observerMom = new ConcreatObserver();        observerMom.setObserverName("老妈");        observerMom.setRemindThing("去逛街了");        //3. 注册观察者        weatherSubject.attach(observerGf);        weatherSubject.attach(observerMom);        //4. 目标发布天气        weatherSubject.setWeatherContent("大暴雨");    }}

这时,我们会得到以下的输出。

女票收到了大暴雨,是我们的第一次约会,地点公园老妈收到了大暴雨,去逛街了

3.5总结

让我们回顾一下整个流程。
首先,我们有我们的主角(目标,被观察者)小陈,和两个他的家人(观察者)。两个家人都去订阅了天气预报的服务。当天气改变时,我们的小陈会依次通知所有的订阅者,订阅者收到通知后,可以自行判断该怎么做。这就是观察者模式。

参考:大话设计模式——观察者模式(一)