zoukankan      html  css  js  c++  java
  • 观察者模式--java jdk中提供的支持

    一、简介

    观察者设计模式有如下四个角色

    • 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现,也可以使用非抽象类来实现。
    • 具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
    • 抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
    • 具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现。

      观察者设计模式类图如下:

    二、java JDK中对观察者的支持
      java JDK中提供了Observer 与 Observable两个类。Observer类可以看作是抽象观察者角色,而Observable是抽象主题角色。

      1、Objserver 

        Objserver 是个接口,代码如下:

    public interface Observer {
        /**
         * 该方法当主题对象发生改变的时候被调用. An
         * 一个应用调用主题对象的notifyObservers方法来application calls an <tt>Observable</tt> object's
         * <code>notifyObservers</code> method to have all the object's
         * observers notified of the change.
         *
         * @param   o     the observable object.
         * @param   arg   an argument passed to the <code>notifyObservers</code>
         *                 method.
         */
        void update(Observable o, Object arg);
    }

      它只提供了一个update,让子类去实现。当主题对象发生改变的时候,就会调用观察者对象的update方法,从而达到观察者发生改变的目的。

      2、Observable

        Observable是个类,代码如下:

    public class Observable {
        private boolean changed = false;
        private Vector obs;//用于存放观察者对象的引用
    
        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);
        }
        
        //通知指定的观察者
        public void notifyObservers(Object arg) { 
            Object[] arrLocal;
    
            synchronized (this) { 
                if (!changed)//当状态没有发生改变的时候,直接返回
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
        //通知并调用观察者的update方法
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        } 
        
        //移除所有观察者
        public synchronized void deleteObservers() {
            obs.removeAllElements();
        } 
    
        //设置状态改变
        protected synchronized void setChanged() {
            changed = true;
        } 
    
        //重置状态
        protected synchronized void clearChanged() {
            changed = false;
        }
    
        //判断是否状态是否发生改变
        public synchronized boolean hasChanged() {
            return changed;
        }
    
        返回观察者的个数
        public synchronized int countObservers() {
            return obs.size();
        }
    }

      从代码可以看出,我们可以让具体主题对象继承Observable类,具体观察者对象实现Observer接口并实现update方法。调用的时候只需要实例化具体主题对象与具体观察者对象,然后将具体观察者对象添加到具体主题对象中的obs(Vector)列表。当具体主题对象的状态发生该变时,调用观察者对象的update方法(这里状态发生该变指的是调用主题对象的某个方法,该方法里面有对具体观察者对象的update方法的调用)。

    三、实例

      具体观察者对象

    具体主题对象
    package com.observer;
    
    import java.util.Observable;
    /**
     * 具体主题对象
     *
     */
    public class ConcreteSubject extends Observable {
    
        private String info;
    
        public String getInfo() {
            return info;
        }
    
        public void setInfo(String info) {
            this.info = info;
        }
    
        public void doSomething(String str) {
            System.out.println("subject: " + str);
            setInfo(str);
            setChanged();//改变主题对象的状态,这里如果不改变它的状态,则不会对观察者对象调用update方法
    //        notifyObservers();//也可以不传递参数
            notifyObservers("subject is changed");//这里传递的参数是观察者对象中update方法参数列表中的第二个参数
        }
    }

      具体观察者对象

    package com.observer;
    
    import java.util.Observable;
    import java.util.Observer;
    /**
     * 具体观察者对象
     *
     */
    public class ConcreteObserver implements Observer {
    
        /**
         * @param subject  具体主题对象
         * @param arg notifyObservers(String str) 传递的参数
         */
        public void update(Observable o, Object arg) {
            System.out.println(arg);
            
            ConcreteSubject subject = (ConcreteSubject)o;
            System.out.println("observer: " + subject.getInfo());
        }
    } 

      调用代码:

    package com.observer;
    
    import java.util.Observer;
    
    public class Test {
        public static void main(String[] args) {
            //观察者对象
            Observer observer = new ConcreteObserver();
            Observer observer2 = new ConcreteObserver();
            Observer observer3 = new ConcreteObserver();
    
            //主体对象
            ConcreteSubject observable = new ConcreteSubject();
            
            //观察者加入主题对象汇总的观察者列表
            observable.addObserver(observer);
            observable.addObserver(observer2);
            observable.addObserver(observer3);
    
            //主体对象发生改变
            observable.doSomething("happy");
            observable.doSomething("sad");
        }
    }

                                                     

  • 相关阅读:
    学习进度
    作业8:单元测试练习
    用户体验设计案例分析
    团队协作一
    需求分析
    结对编程——词频统计 2
    结对编程——词频统计
    个人项目-词频统计
    数组求和
    个人介绍和Github使用流程
  • 原文地址:https://www.cnblogs.com/always-online/p/4284399.html
Copyright © 2011-2022 走看看