设计模式之观察者模式

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

二、Demo

该实例模拟了烧水的过程,涉及三个对象,Heater(热水器),Display(显示器),Alarm(报警器).

1.热水器

package com.design.observer;

import java.util.Observable;

/**
 * 类名称:Heater
 * 
 * 描述:观察者模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新
 *     观察对象即被观察者:继承Observable
 *     观察者:实现Observer接口
 * 
 * 热水器类Heater:Display观察对象即被观察者(subject)
 * 显示器类Display:Heater的观察者,同时也是Alarm的观察对象;即是观察者也是被观察者
 * 报警器类Alarm:Display的观察者
 * 
 * 本实例逻辑:
 * 显示器依据热水器显示温度,显示器显示温度为100时,报警器开始报警。
 * 修改备注:
 * 版本:1.0.1
 *
 */
public class Heater extends Observable {
    private Integer temp;//水温度

    public Integer getTemp() {
        return temp;
    }

    public void setTemp(Integer temp) {
        this.temp = temp;
    }
    
    public void boilWater() {
       for (int i = 90; i < 110; i++) {
           temp = i;
           
           this.setChanged();//标记此观察者对象发生变化
           this.notifyObservers();//通知观察者,即告诉显示器温度发生变化,显示屏显示需要变更最新温度

       }
    }
}

2.显示器

package com.design.observer;

import java.util.Observable;
import java.util.Observer;

/**
 * 类名称:Display
 * 
 * 显示器:显示水的温度,当水温度发生变化时,显示随着变化,
 * 当水沸腾时通知报警器报警
 * 修改备注:
 * 版本:1.0.1
 *
 */
public class Display extends Observable implements Observer {

    private String status="未开";
    
    /**
     * 接收观察对象的信息,更新观察者自己的状态
     * 
     */
    @Override
    public void update(Observable o, Object arg) {
        this.displayTemperature(((Heater)o).getTemp());
    }
    
    /**
     * 被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应
     * 〈功能详细描述〉
     * 当接收观察对象(被观察者)的温度沸腾信息时,变更状态;
     * 并通知告知自己的观察者,变更状态
     * 
     */
    private void displayTemperature(int temperature) {
       if (temperature >= 100) {
           this.setStatus("水沸腾啦。。。。。");//水沸腾
           
           this.setChanged();//标记此观察者对象发生变化
           this.notifyObservers(temperature);//通知观察者,即告诉报警器水已沸腾,报警器报警
       }

       System.out.println("状态: " + status + "  现在温度: " + temperature);

    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

}

3.报警器

package com.design.observer;

import java.util.Observable;
import java.util.Observer;

/**
 * 类名称:Alarm
 * 
 * 报警器:当水沸腾时,报警;根据Display传过来的温度信息判断
 * 修改备注:
 * 版本:1.0.1
 *
 */
public class Alarm implements Observer {

    //收到通知,更新自己
    //被观察者发生改变,观察者观察到这样的变化,并且做出相应的响应
    @Override
    public void update(Observable o, Object arg) {
        this.makeAlarm((Integer)arg);
    }
    
    private void makeAlarm(int temperature) {
       System.out.println("报警器:滴滴滴滴滴。。。水已经烧开了");
    }

}

4.测试

package com.design.observer;

//测试类  TestObserver
public class TestObserver {

    public static void main(String[] args) {

       Heater heater = new Heater();

       Display display = new Display();

       Alarm alarm = new Alarm();

       heater.addObserver(display);//显示器设置为热水器的观察者

       display.addObserver(alarm);//报警器设置为显示器的观察者

       heater.boilWater();//热水器烧水

    }

}

5.测试结果:

三、观察者模式优缺点:

优点:

第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

缺点:

第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

 

posted @ 2017-08-29 15:45  High阔天空  阅读(226)  评论(0编辑  收藏  举报