观察者模式

来源:互联网 发布:小号软件 编辑:程序博客网 时间:2024/06/08 09:36
解决的问题:当一个类的状态变化需要通知多个类,且被通知的类型要动态变化时,就可以使用观察者模式。
标准定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。

类结构图如下:


类图中Observable类是被观察者,Observer接口为观察者定义了规范方法,该方法由被观察者进行通知。观察者模式遵循迪米特原则,被观察者通过Observer接口感知观察者,无需关心具体的观察者有哪些类型,将观察者与被观察者解耦。

Observable和Observer已集成在JDK中。在使用中,通过继承Observable创建被观察者;通过实现Observer接口定义观察者。下面先看一个航班起飞通知的例子:
//被观察者public class FlightNotice extends Observable {    private String no;    private Date date;    FlightNotice(String no,Date date) {        super();        this.no = no;        this.date = date;        NoticeSystem.getInstance().addSource(this);    }    public void addPassenger(Passenger passenger) {        super.addObserver(passenger);    }    public void noticeAll() {        super.setChanged();//设置状态变化        super.notifyObservers();//通知观察者    }    public String getNo() {        return no;    }    public void setNo(String no) {        this.no = no;    }    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }}
//观察者public class Passenger implements Observer{    private String name;    public Passenger(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public void register(String flightNo) {        FlightNotice flightNotice = NoticeSystem.getInstance().getNotice(flightNo);        if (flightNotice != null) {            flightNotice.addPassenger(this);        }    }    @Override    public void update(Observable o, Object arg) {        FlightNotice notice = (FlightNotice) o;        System.out.println("dear " + name);        System.out.println("flight " + notice.getNo() + " will leave at " + DateFormatUtils.format(notice.getDate(), DateFormatUtils.ISO_DATETIME_FORMAT.getPattern()));    }}
//通知管理public class NoticeSystem {    private static final NoticeSystem register = new NoticeSystem();    private Map<String, FlightNotice> flightNoticeMap = Maps.newHashMap();    private NoticeSystem() {    }    public static NoticeSystem getInstance() {        return register;    }    public void addSource(FlightNotice flightNotice) {        this.flightNoticeMap.put(flightNotice.getNo(), flightNotice);    }    public FlightNotice getNotice(String no) {        return flightNoticeMap.get(no);    }}
public class TestObserver {    public static void main(String[] args) {        FlightNotice notice = new FlightNotice("sz100-1", new Date());        Passenger cds = new Passenger("cds");        Passenger niko = new Passenger("niko");        cds.register("sz100-1");        niko.register("sz100-1");        notice.noticeAll();    }}输出如下:dear nikoflight sz100-1 will leave at 2017-06-23T21:04:32dear cdsflight sz100-1 will leave at 2017-06-23T21:04:32
在上述代码中,FlightNotice是被观察者,Passenger是观察者,NoticeSystem是通知管理器,管理所有被观察者。
创建一个FlightNotice即定义一个主题,放入到通知管理器中;观察者通过register决定自己要订阅的主题;当主题状态变化时,通过notifyObservers通知所有观察者。

以下是Observal源码:
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);    }    /**    * If this object has changed, as indicated by the    * <code>hasChanged</code> method, then notify all of its observers    * and then call the <code>clearChanged</code> method to indicate    * that this object has no longer changed.    * <p>    * Each observer has its <code>update</code> method called with two    * arguments: this observable object and the <code>arg</code> argument.    *    */    public void notifyObservers(Object arg) {        /*        * a temporary array buffer, used as a snapshot of the state of        * current Observers.        */        Object[] arrLocal;        synchronized (this) {            /* We don't want the Observer doing callbacks into            * arbitrary code while holding its own Monitor.            * The code where we extract each Observable from            * the Vector and store the state of the Observer            * needs synchronization, but notifying observers            * does not (should not).  The worst result of any            * potential race-condition here is that:            * 1) a newly-added Observer will miss a            *  notification in progress            * 2) a recently unregistered Observer will be            *  wrongly notified when it doesn't care            */            if (!changed)                return;            arrLocal = obs.toArray();            clearChanged();        }        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();    }}







原创粉丝点击