《Head Frist 设计模式》学习笔记——观察者模式

《Head Frist 设计模式》学习笔记——观察者模式


1.主题+观察者=观察者模式

2.观察者模式定义

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

3.定义观察者模式

优点

  • 观察者模式提供了一种对象设计,让主题和观察者之间松耦合。
  • 主题只知道观察者实现了某个接口,不需要知道观察者的具体类是谁、做了哪些操作。
  • 任何时候我们都可以增加新的观察者,或删除已有的观察者。
  • 有新的观察者时,主题的代码不需要修改。主题只负责发送通知给所有实现了观察者接口的对象。

4.示例(书中是以一个气象站的实现作为示例)

  • Subject

    public interface Subject{
        public void registerObserver(Observer o);
        public void removeObserver(Observer o);
        public void notifyObservers();
    }
    
    public interface Observer{
        public void update(float temp);
    }
    
    public interface DisplayElement{
        public void display();
    }
    
  • WeatherData

    public class WeathData implements Subject{
    
        private ArrayList observers;
        private float temp;
    
        public void registerObserver(Observer o){
            observers.add(o);
        }
    
        public void removeObserver(Observer o){
            int i = observers.indexOf(o);
            if(i >= 0){
                observers.remove(i);
            }
        }
    
        public void notifyObservers(){
            for(int i = 0;i < observers.size();i++){
                Observer observer = (Observer)observers.get(i);
                observer.update(temp);
            }
        }
    
        public void measurementsChanged(){
            notifyObservers();
        }
    
        public void setMeasurements(float temp){
            this.temp = temp;
            measurementsChanged();
        }
    
        //WeatherData的其他方法
    }
    
  • CurrentConditionsDisplay

    public class CurrentConditionsDisplay implements Observer,DisplayElement{
    
        private float temp;
        private Subject weatherData;
    
        public CurrentConditionsDisplay(Subject weatherData){
            this.weatherData = weaterhData;
            weatherData.registerObserver(this);
        }
    
        public void update(float temp){
            this.temp = temp;
            display();
        }
    
        public void display(){
            System.out.println("Current conditions: " + temp);
        }
    }
    
  • 测试程序

    WeatherData weatherData = new WeatherData();
    CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
    
    weatherData.setMeasurements(80);
    
  • 实现过程

5.Java中内置的观察者模式

Java API有内置的观察者模式,java.util包(package)内包含最基本的Observer接口(与我们自己定义的Subject接口类似)与Observable类
- Observer接口

    /**
     * {@code Observer} is the interface to be implemented by objects that
     * receive notification of updates on an {@code Observable} object.
     *
     * @see Observable
     */
    public interface Observer {

        /**
         * This method is called if the specified {@code Observable} object's
         * {@code notifyObservers} method is called (because the {@code Observable}
         * object has been updated.
         *
         * @param observable
         *            the {@link Observable} object.
         * @param data
         *            the data passed to {@link Observable#notifyObservers(Object)}.
         */
        void update(Observable observable, Object data);
    }
  • Observable类

    /**
     * Observable is used to notify a group of Observer objects when a change
     * occurs. On creation, the set of observers is empty. After a change occurred,
     * the application can call the {@link #notifyObservers()} method. This will
     * cause the invocation of the {@code update()} method of all registered
     * Observers. The order of invocation is not specified. This implementation will
     * call the Observers in the order they registered. Subclasses are completely
     * free in what order they call the update methods.
     *
     * @see Observer
     */
    public class Observable {
    
        List<Observer> observers = new ArrayList<Observer>();
    
        boolean changed = false;
    
        /**
         * Constructs a new {@code Observable} object.
         */
        public Observable() {
        }
    
        /**
         * Adds the specified observer to the list of observers. If it is already
         * registered, it is not added a second time.
         *
         * @param observer
         *            the Observer to add.
         */
        public void addObserver(Observer observer) {
            if (observer == null) {
                throw new NullPointerException("observer == null");
            }
            synchronized (this) {
                if (!observers.contains(observer))
                    observers.add(observer);
            }
        }
    
        /**
         * Clears the changed flag for this {@code Observable}. After calling
         * {@code clearChanged()}, {@code hasChanged()} will return {@code false}.
         */
        protected void clearChanged() {
            changed = false;
        }
    
        /**
         * Returns the number of observers registered to this {@code Observable}.
         *
         * @return the number of observers.
         */
        public int countObservers() {
            return observers.size();
        }
    
        /**
         * Removes the specified observer from the list of observers. Passing null
         * won't do anything.
         *
         * @param observer
         *            the observer to remove.
         */
        public synchronized void deleteObserver(Observer observer) {
            observers.remove(observer);
        }
    
        /**
         * Removes all observers from the list of observers.
         */
        public synchronized void deleteObservers() {
            observers.clear();
        }
    
        /**
         * Returns the changed flag for this {@code Observable}.
         *
         * @return {@code true} when the changed flag for this {@code Observable} is
         *         set, {@code false} otherwise.
         */
        public boolean hasChanged() {
            return changed;
        }
    
        /**
         * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
         * method for every observer in the list of observers using null as the
         * argument. Afterwards, calls {@code clearChanged()}.
         * <p>
         * Equivalent to calling {@code notifyObservers(null)}.
         */
        public void notifyObservers() {
            notifyObservers(null);
        }
    
        /**
         * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
         * method for every Observer in the list of observers using the specified
         * argument. Afterwards calls {@code clearChanged()}.
         *
         * @param data
         *            the argument passed to {@code update()}.
         */
        @SuppressWarnings("unchecked")
        public void notifyObservers(Object data) {
            int size = 0;
            Observer[] arrays = null;
            synchronized (this) {
                if (hasChanged()) {
                    clearChanged();
                    size = observers.size();
                    arrays = new Observer[size];
                    observers.toArray(arrays);
                }
            }
            if (arrays != null) {
                for (Observer observer : arrays) {
                    observer.update(this, data);
                }
            }
        }
    
        /**
         * Sets the changed flag for this {@code Observable}. After calling
         * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
         */
        protected void setChanged() {
            changed = true;
        }
    }
    

使用方法

  • 注册和解注册观察者

    • 实现观察者接口(java.util.Observer)
    • 调用addObserver()方法成为观察者
    • 调用deleteObserver()方法解注册观察者
  • 发送通知

    • 继承java.util.Observable生成“被观察者”类
    • 调用setChanged()方法

      用来标记状态已经改变的事实,调用notifyObservers()方法之前必须先调用setChanged(),否则观察者不会被通知
      
      setChanged(){
          changed = true;
      }
      
      notifyObservers(Object arg){
          if(changed){
              for every observer on the list{
                  call update(this,arg);
              }
              changed = false;
          }
      }
      
      notifyObservers(){
          notifyObservers(null);
      }
      
    • 调用notifyObservers()或notifyObservers(Object arg)

      • notifyObservers()会调用notifyObservers(Object arg)

        public void notifyObservers() {
            notifyObservers(null);
        }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值