观察者模式

介绍

观察者模式(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。 --百度百科

观察者模式是一种对象行为模式。当然必须存在两种对象,观察者和被观察值,当被观察者行为状态发生变化,观察者则会被通知到并根据预设的逻辑产生相应的行为变化。

观察者模式更像是一种发布订阅关系,比如微信公众号订阅和微博关注,当公众号或者博主发布消息时,订阅者就会收到消息通知。该模式主要目的就是解耦合,使观察者与被观察者分离开。

当然也可以有多个观察者与多个被观察者,一个对象可以作为观察者,也可以被其他对象所观察。

Java中的观察者应用

jdk为我们提供了观察者模式的java类

  • java.util.Observable(被观察者继承)
public class Observable {
    private boolean changed = false; // 变化标识
    private Vector<Observer> 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);
    }

    /**
     * 当被观察者发生变化,通知所有观察者
     * @param   arg   any object.更新的对象信息
     */
    public void notifyObservers(Object arg) {
        /*
		 * 临时缓存数组,相当于当前观察者状态的快照
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
            /* 
             * 同步代码块
             * 1)避免新添加观察者错过通知
             * 2)避免最近取消订阅的观察者错误通知
             */
            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();
    }
}

  • java.util.Observer(观察者接口实现)
public interface Observer {
    /**
     * 当订阅的被观察者发出通知执行该方法
     */
    void update(Observable o, Object arg);
}

观察者需要重写Observer的update方法。被观察者通过addObservers方法添加观察者

HelloWorld

场景:智能家居
当下班回家时打开门(通知)开启空调电视,开灯。

观察者对象

  • 空调
public class AirConditioner implements Observer{
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("打开空调");
    }
}
  • 电视
public class Television implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("打开电视");
    }
}
public class Light implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("打开灯");
    }
}

被观察者

public class Master extends Observable {
    public void openDoor(){
        System.out.println("回到家打开门");
		// 修改状态
        this.setChanged();
        this.notifyObservers();
    }
}

通知测试

public class Test {
    public static void main(String[] args) {
        //创建观察者
        Light light = new Light();
        Television television = new Television();
        AirConditioner airConditioner = new AirConditioner();
        //创建被观察者
        Master master = new Master();
        //添加观察者
        master.addObserver(light);
        master.addObserver(television);
        master.addObserver(airConditioner);
        // 行为改变,发布通知
        master.openDoor();
    }
}

观察者模式其实很容易理解,状态的改变然后通知观察者做出相应的逻辑处理。同一个观察者也可以订阅多个被观察者。可以简单的理解为发布订阅关系

posted @ 2019-08-16 15:57  fxtahe  阅读(42)  评论(0)    收藏  举报