Java设计模式——观察者模式

来源:互联网 发布:sublime java插件 编辑:程序博客网 时间:2024/05/20 06:23

未使用JDK相关类实现的观察者模式

观察者设计模式适合解决多种对象跟踪一个对象数据变化的程序结构问题,有一个称作“主题”的对象和若干个称作“观察者”的对象。

代码:

//1.      观察者接口/** * 观察者接口IObserver * @author Goser    (mailto:goskalrie@163.com) * @Since 2016年9月5日 */public interface IObserver {    public void refresh(String data);}//2.      主题接口public interface ISubject {    /**     * 注册观察者     * @param obs     */    public void register(IObserver obs);       /**     * 注销观察者     * @param obs     */    public void unregister(IObserver obs);       /**     * 通知所有观察者     */    public void notifyObservers();}//3.      主题实现类public class Subject implements ISubject {    //观察者维护向量    private Vector<IObserver> vec = new Vector<IObserver>();    //主体中心数据    private String data;       public String getData(){        return data;    }       public void setData(String data){        this.data = data;    }       public void register(IObserver obs) {        vec.add(obs);    }     public void unregister(IObserver obs) {        if(vec.contains(obs)){            vec.remove(obs);        }    }     public void notifyObservers() {        for(int i = 0; i < vec.size(); i++){            IObserver obs = vec.get(i);            obs.refresh(data);        }    } }//4.      一个具体观察者public class Observer implements IObserver {    public void refresh(String data) {        System.out.println("I have received the data:" + data);    } }//5.一个简单测试类public class ObserverTest {    public static void main(String[] args) {        IObserver obs = new Observer();        Subject subject = new Subject();        subject.register(obs);        subject.setData("Hello");        subject.notifyObservers();    }}//输出结果:I have received the data:Hello
这段代码的含义是:当主题中心数据变化(通过setData方法)后,主题类subjeect要调用notifyObservers()方法,通知所有观察者对象接收数据并进行数据响应。

JDK中的观察者设计模式

由于观察者设计模式中主题功能及观察者接口定义内容的稳定性,JDK的java.util包提供了系统的主题类Observable及观察者接口Observer,很明显,Observer相当于前面的Iobserver观察者接口,其中的update()方法中第一个参数是Observable类型,表明采用的“拉”数据方式;Observable相当于前面的主题类Subject,addObserver()、deleteObserver()、notifyObservers()三个方法分别表示添加、删除、通知观察者对象功能。

利用JDK中的Observer、Observable完成观察者模式:

//1.      编制主题类JSubjectpublic class JSubject extendsObservable {    String data;     public String getData() {        return data;    }     public void setData(String data) {        this.data = data;        setChanged();        notifyObservers(null);    }} //2.      编制具体观察者类OneObserverpublic class OneObserver implements java.util.Observer{    public void update(Observable o, Object arg) {        JSubject subject = (JSubject)o;        System.out.println("The data is:" + subject.getData());//"拉"数据    }}//3.测试类public class ObserverTest {    public static void main(String[] args) {        java.util.Observer obj = new OneObserver();        JSubject s = new JSubject();        s.addObserver(obj);        s.setData("Hello");    }}
对于源码感兴趣的可以看下后面的源码,不感兴趣的直接掠过,但是专家级的代码——多看。

源码分析:

//1.java.util. Observablepublic class Observable {    private boolean changed = false;//用于保存主题状态    private Vector obs;//用于保存主题的观察者     /**构造一个含有零个观察者的主题对象 */     public Observable() {        obs = new Vector();    }     /**当该主题没有此观察者时添加该观察者,向集合中观察者通知的顺序不是固定的*/    public synchronized voidaddObserver(Observer o) {        if (o == null)            throw new NullPointerException();        if (!obs.contains(o)) {            obs.addElement(o);        }    }     /**从对象的观察者集合中删除某个观察者。向此方法传递 null 将使其无效。*/    public synchronized voiddeleteObserver(Observer o) {        obs.removeElement(o);    }     /** 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。*/    public void notifyObservers() {        notifyObservers(null);    }     /** 同上*/    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 voiddeleteObservers() {        obs.removeAllElements();    }     /**标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。*/    protected synchronized void setChanged() {        changed = true;    }     /**     * 指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。     * notifyObservers 方法自动调用此方法。     */    protected synchronized void clearChanged(){        changed = false;    }     /** 测试对象是否改变。*/    public synchronized booleanhasChanged() {        return changed;    }     /** 返回 Observable 对象的观察者数目。*/    public synchronized intcountObservers() {        return obs.size();    }}//2.java.util.Observerpublic interface Observer {    void update(Observable o, Object arg);}

使用JDK中的Observer、Observable完成观察者模式总结:

1.      编制主题类时直接继承java.util.Observable类,在该类中主要定义各中心数据及get、set方法。get方法主要用于具体观察者“拉”数据。set方法主体要用于更新数据、设置changed变量及通知各具体观察者进行数据响应。

2.      编制具体观察者时需要实现java.util.Observer接口(有观察的权限)其中update()方法主要完成“拉”数据及处理过程。

从测试代码中看观察者模式的实质:

java.util.Observerobj = new OneObserver();JSubject s = new JSubject();s.addObserver(obj);s.setData("Hello");
首先创建了一个Observer观察者对象(obj)和一个Observable主题对象(o),之后向s中添加了obj这个观察者,也就是在s中的vec变量中存有了obj的引用,调用s.setData()方法时,该方法中有这样两句:

#1  setChanged();

#2  notifyObservers(null);

代码一是改变主题状态:已经通知完各观察者,状态应为未改变。

代码二是通知所有观察者。

查看源码知道notifyObservers()方法中通知各观察者的实际操作代码是调用Observer中的update()方法。

从以上分析中不难发现,观察者模式的实际含义是:在主题类中调用观察者的update方法,以此来通知观察者:我改变了,快来取我改变的内容。(此操作是底层源码中进行的,我们编写的代码中完成的操作是调用notifyObservers()方法)。

0 0
原创粉丝点击