观察者模式 Java

来源:互联网 发布:mysql查看root密码 编辑:程序博客网 时间:2024/06/08 06:46

观察者模式 Java

观察者模式(Observer Pattern)指多个观察者同时依赖于某个主题对象,对象发生改变后会主动通知观察者进行改变的软件设计模式。


主要内容:

  1. 简要原理
  2. 观察者模式实例
  3. 完整工程链接

简要原理

百度百科:
观察者模式

别名:发布(publish)-订阅(subscribe)模式、模型(model)-视图(view)模式、源-收听者模式、从属者模式

观察者模式有两个主要对象:观察者和被观察者,其中,观察者的功能实现依赖于被观察者(比如,观察者是前端界面,被观察者是后台数据,界面需要利用后台数据进行界面展示),当观察者观察到被观察者的状态发生变化后,自身也随之发生变化(比如,界面显示天气信息,当后台天气数据发生变化后,前端会根据变化的数据重新构建界面)。

实现:并不是观察者时刻关注被观察者是否发生变化,而是被观察者包含有观察者对象,而观察者则具体实现了更新方法,当被观察者自身发生变化后,遍历观察者列表,调用更新方法,通知观察者进行相应的变化(即订阅 - 通知 - 撤销订阅的结构)。


观察者模式实例

参考:

设计模式学习笔记-观察者模式

观察者模式

设计模式之观察者模式

首先定义一个抽象主题,里面实现绑定、撤销、通知观察者的方法,Subject.java 代码如下:

package ObserverModel2;import java.util.ArrayList;import java.util.List;/** * Created by Lenovo on 2017/5/15. */public abstract class Subject {    private List<Observer> list = new ArrayList<>();    /**     * 订阅     *     * @param observer     */    public void Attach(Observer observer) {        list.add(observer);    }    /**     * 撤销订阅     *     * @param observer     */    public void Detach(Observer observer) {        list.remove(observer);    }    /**     * 通知     */    public void Notify() {        System.out.println("Update:");        for (Observer observer : list) {            observer.Update();        }    }}

被观察者中包含有一个气候对象(WeatherBean),其中包含有季节(season)、天气(weather),WeatherBean.java 代码如下:

package ObserverModel2;/** * Created by Lenovo on 2017/5/15. */public class WeatherBean {    /**     * 季节:春夏秋冬     */    private String season;    /**     * 天气:冷、热     */    private String weather;    public WeatherBean(String season, String weather) {        this.season = season;        this.weather = weather;    }    public String getSeason() {        return season;    }    public void setSeason(String season) {        this.season = season;    }    public String getWeather() {        return weather;    }    public void setWeather(String weather) {        this.weather = weather;    }    @Override    public String toString() {        return "WeatherBean{" +                "season='" + season + '\'' +                ", weather='" + weather + '\'' +                '}';    }}

具体实现被观察者,ConcreteSubject.java 如下:

package ObserverModel2;/** * Created by Lenovo on 2017/5/15. */public class ConcreteSubject extends Subject {    private WeatherBean weatherBean;    public ConcreteSubject(WeatherBean weatherBean) {        this.weatherBean = weatherBean;    }    /**     * 设置季节变换和天气变换     *     * @param weatherBean     */    public void setWeatherBean(WeatherBean weatherBean) {        this.weatherBean = weatherBean;        this.Notify();    }    public WeatherBean getWeatherBean() {        return weatherBean;    }    /**     * 季节变换     *     * @param season     */    public void setSeason(String season) {        weatherBean.setSeason(season);        this.Notify();    }    /**     * 天气变换     *     * @param weather     */    public void setWeather(String weather) {        weatherBean.setWeather(weather);        this.Notify();    }    @Override    public String toString() {        return "ConcreteSubject{" +                "weatherBean=" + weatherBean +                '}';    }}

定义一个接口,包含观察者需要实现的更新方法,以便被观察者统一调用,Observable.java 代码如下:

package ObserverModel2;/** * Created by Lenovo on 2017/5/15. */public interface Observable {    /**     * 更新接口     */    void Update();}

观察者 Observer.java 代码如下:

package ObserverModel2;/** * Created by Lenovo on 2017/5/15. */public class Observer implements Observable {    /**     * 观察者     */    private String name;    /**     * 具体主题     */    private ConcreteSubject subject;    public Observer(String name, ConcreteSubject subject) {        this.name = name;        this.subject = subject;        // 绑定观察者        this.subject.Attach(this);        Update();    }    @Override    public void Update() {        String str = String.format("name: %s subject: %s", name, subject.toString());        System.out.println(str);    }}

测试代码 Test.java 如下:

package ObserverModel2;/** * Created by Lenovo on 2017/5/16. */public class Test {    public static void main(String[] args) {        ConcreteSubject subject = new ConcreteSubject(new WeatherBean("spring", "warm"));        Observer observer = new Observer("one", subject);        Observer observer1 = new Observer("two", subject);        Observer observer2 = new Observer("three", subject);        // 修改对象        subject.setSeason("summary");        subject.setWeather("hot");    }}

实现结果:

这里写图片描述

利用Java自带可观察对象 Observable

参考:

Interface Observer:抽象观察者

Class Observable:可观察对象

Java 自带了抽象主题(Observable),以及更新接口(Observer

修改后具体主题(ConcreteSubject.java)代码如下:

package ObserverModel3;import ObserverModel2.WeatherBean;import java.util.Observable;/** * Created by Lenovo on 2017/5/16. */public class ConcreteSubject extends Observable {    private WeatherBean weatherBean;    public ConcreteSubject(WeatherBean weatherBean) {        this.weatherBean = weatherBean;    }    /**     * 设置季节变换和天气变换     *     * @param weatherBean     */    public void setWeatherBean(WeatherBean weatherBean) {        this.weatherBean = weatherBean;        Notify();    }    public WeatherBean getWeatherBean() {        return weatherBean;    }    /**     * 季节变换     *     * @param season     */    public void setSeason(String season) {        weatherBean.setSeason(season);        Notify();    }    /**     * 天气变换     *     * @param weather     */    public void setWeather(String weather) {        weatherBean.setWeather(weather);        Notify();    }    @Override    public String toString() {        return "ConcreteSubject{" +                "weatherBean=" + weatherBean +                '}';    }    private void Notify() {        System.out.println("Update:");        this.setChanged();        this.notifyObservers(weatherBean);    }}

具体观察者(ConcreteObserver.java)代码如下:

package ObserverModel3;import ObserverModel2.WeatherBean;import java.util.Observable;import java.util.Observer;/** * Created by Lenovo on 2017/5/16. */public class ConcreteObserver implements Observer {    /**     * 观察者     */    private String name;    /**     * 具体主题     */    private ConcreteSubject subject;    public ConcreteObserver(String name, ConcreteSubject subject) {        this.name = name;        this.subject = subject;        // 绑定观察者        this.subject.addObserver(this);        this.update(null, null);    }    @Override    public void update(Observable o, Object arg) {        String str = null;        if (arg != null) {            WeatherBean bean = (WeatherBean) arg;            str = String.format("name: %s subject: %s", name, bean.toString());        } else {            str = String.format("name: %s subject: %s", name, subject.toString());        }        System.out.println(str);    }}

测试代码(Test.java)如下:

package ObserverModel3;import ObserverModel2.WeatherBean;/** * Created by Lenovo on 2017/5/16. */public class Test {    public static void main(String[] args) {        ConcreteSubject subject = new ConcreteSubject(new WeatherBean("spring", "warm"));        ConcreteObserver observer = new ConcreteObserver("one", subject);        ConcreteObserver observer1 = new ConcreteObserver("two", subject);        ConcreteObserver observer2 = new ConcreteObserver("three", subject);        // 修改对象        subject.setSeason("summary");        subject.setWeather("hot");    }}

完整工程链接

https://git.oschina.net/zjZSTU/observerdemo.git