观察者模式

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

类结构图如下:

观察者模式_第1张图片
类图中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 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 niko
flight sz100-1 will leave at 2017-06-23T21:04:32
dear cds
flight 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
    * hasChanged method, then notify all of its observers
    * and then call the clearChanged method to indicate
    * that this object has no longer changed.
    * 

* Each observer has its update method called with two * arguments: this observable object and the arg 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(); } }








你可能感兴趣的:(设计模式,观察者模式)