JAVA设计模式之观察者模式

来源:互联网 发布:金山数据大师破解版 编辑:程序博客网 时间:2024/06/02 04:46

一、观察者模式又叫做发布-订阅(Publish/Subscribe)模式。是属于行为型模式的一种。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。这里的主题对象就是指通知者,又叫做发布者。观察者又叫订阅者。

主要解决的问题:为了防止当我们需要维护对象间的一致性的同时造成各类之间紧密耦合,给维护、扩展和重用都带来不便。

二、 模式中的角色

  1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

  2 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

  3 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

  4 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

三、具体实现

 1、抽象主题角色类

public abstract class Subject {    /**     * 用来保存注册的观察者对象     */    private    List<Observer> list = new ArrayList<Observer>();    /**     * 注册观察者对象     * @param observer    观察者对象     */    public void attach(Observer observer){        list.add(observer);        System.out.println("Attached an observer");    }    /**     * 删除观察者对象     * @param observer    观察者对象     */    public void detach(Observer observer){        list.remove(observer);    }    /**     * 通知所有注册的观察者对象     */    public void nodifyObservers(String newState){        for(Observer observer : list){            observer.update(newState);        }    }}

2、具体主题角色类

public class ConcreteSubject extends Subject{    private String state;    public String getState() {        return state;    }    public void change(String newState){        state = newState;        System.out.println("主题状态为:" + state);        //状态发生改变,通知各个观察者        this.nodifyObservers(state);    }}

3、抽象观察者角色类

public interface Observer {    /**     * 更新接口     * @param state    更新的状态     */    public void update(String state);}

4、具体观察者角色类

public class ConcreteObserver implements Observer {    //观察者的状态    private String observerState;    @Override    public void update(String state) {        /**         * 更新观察者的状态,使其与目标的状态保持一致         */        observerState = state;        System.out.println("状态为:"+observerState);    }}

5、客户端类

public class Client {    public static void main(String[] args) {        //创建主题对象        ConcreteSubject subject = new ConcreteSubject();        //创建观察者对象        Observer observer = new ConcreteObserver();        //将观察者对象登记到主题对象上        subject.attach(observer);        //改变主题对象的状态        subject.change("new state");    }}

在运行时,这个客户端首先创建了具体主题类的实例,以及一个观察者对象。然后,它调用主题对象的attach()方法,将这个观察者对象向主题对象登记,也就是将它加入到主题对象的聚集中去。

  这时,客户端调用主题的change()方法,改变了主题对象的内部状态。主题对象在状态发生变化时,调用超类的notifyObservers()方法,通知所有登记过的观察者对象。
四、在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持。
1、Observer接口
  这个接口只定义了一个方法,即update()方法,当被观察者对象的状态发生变化时,被观察者对象的notifyObservers()方法就会调用这一方法。

public interface Observer {    void update(Observable o, Object arg);}

2、Observable类
  被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象,这些方法中有两个对Observable的子类非常重要:一个是setChanged(),另一个是notifyObservers()。第一方法setChanged()被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。
  

public class Observable {    private boolean changed = false;    private Vector obs;    /** Construct an Observable with zero Observers. */    public Observable() {    obs = new Vector();    }    /**     * 将一个观察者添加到观察者聚集上面     */    public synchronized void addObserver(Observer o) {        if (o == null)            throw new NullPointerException();    if (!obs.contains(o)) {        obs.addElement(o);    }    }    /**     * 将一个观察者从观察者聚集上删除     */    public synchronized void deleteObserver(Observer o) {        obs.removeElement(o);    }    public void notifyObservers() {    notifyObservers(null);    }    /**     * 如果本对象有变化(那时hasChanged 方法会返回true)     * 调用本方法通知所有登记的观察者,即调用它们的update()方法     * 传入this和arg作为参数     */    public void notifyObservers(Object arg) {        Object[] arrLocal;    synchronized (this) {        if (!changed)                return;            arrLocal = obs.toArray();            clearChanged();        }        for (int i = arrLocal.length-1; i>=0; i--)            ((Observer)arrLocal[i]).update(this, arg);    }    /**     * 将观察者聚集清空     */    public synchronized void deleteObservers() {    obs.removeAllElements();    }    /**     * 将“已变化”设置为true     */    protected synchronized void setChanged() {    changed = true;    }    /**     * 将“已变化”重置为false     */    protected synchronized void clearChanged() {    changed = false;    }    /**     * 检测本对象是否已变化     */    public synchronized boolean hasChanged() {    return changed;    }    /**     * Returns the number of observers of this <tt>Observable</tt> object.     *     * @return  the number of observers of this object.     */    public synchronized int countObservers() {    return obs.size();    }}

 这个类代表一个被观察者对象,有时称之为主题对象。一个被观察者对象可以有数个观察者对象,每个观察者对象都是实现Observer接口的对象。在被观察者发生变化时,会调用Observable的notifyObservers()方法,此方法调用所有的具体观察者的update()方法,从而使所有的观察者都被通知更新自己。

参考链接:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 钢铁雄心4无模板怎么办 登录 新浪微博登录异常怎么办 微博授权失败怎么办qq uc微博授权失败怎么办 苹果手机无线网坏了怎么办 小米手机wife信号不好怎么办 微博出错了c403怎么办 微信客服没人接怎么办 安装包解析错误怎么办平板 苹果手机新浪免费邮箱用不了怎么办 苹果手机老是弹跳邮箱登陆怎么办 qq长时间不登录上不了怎么办 父母不会说英语怎么办英国签证 美军舰真来台湾怎么办 现役军人回家探亲和人打架怎么办 对四六不懂的人怎么办 赌球小2.5进3球怎么办 皮肤旧伤黑色斑怎么办 小米5c网络不好怎么办 小米去5c卡怎么办 戴尔游匣5577开机黑屏怎么办 三星s6的通知栏拉不下来怎么办 电脑记住密码打不开了怎么办 联想手机升级系统失败了怎么办 日本语言学校申请研究生签证怎么办 在埃塞俄比亚签证过期了怎么办 看完的小说想要卖掉该怎么办 在俄罗斯脸干了痛怎么办 苹果手表电池放亏了怎么办 平板电脑电池不耐用怎么办 计算机电池放入后没反应怎么办 笔记本电脑玩游戏花屏怎么办 笔记本玩游戏花屏怎么办 笔记本电脑充电插口坏了怎么办 车蓄电池没电了怎么办 汤浅q85电瓶亏电怎么办 富士康自离行李怎么办 微店红酒食品认证怎么办 yy频道提示禁止游客进入怎么办 口红颜色太艳了怎么办 我在菲律宾想走怎么办