Java API 设计模式之观察者(Observer)

     这是一个行为型设计模式,是MVC体系结构的基础。    

     Java API 包含了运用观察器设计模式的类。类java.util.Observable代表一个主题。类Observable提供了方法addObserver,该方法带有一个java.util.Observer参数。接口Observer允许Observable对象在其发生状态改变时向Observer发出通知。这个Observer可以是任何一个实现接口Observer的类的实例。因为Observable对象调用在接口Observer中定义的方法,这些对象仍然保持松散耦合关系。如果开发人员改变了一个具体Observer响应Observable对象状态发生改变时的方式,他不必改变这个Observable对象。Observable对象仅仅通过接口Observer与它的Observer进行交互,这保证了松散耦合。

     Swing GUI 组件运用了观察者设计模式。GUI组件与它们的监听器进行协作,以响应用户交互。比如,一个ActionListener通过注册处理一个JButton(主题)的事件而观察JButton的状态变化。当按钮被用户按下后,这个JButton通知它的ActionListener对象(观察器),它的状态已经发生改变。

     假定我们希望设计一个用来查看银行账户信息的程序。此系统包括类BankStatementData(它存储银行结单的数据)以及用来显示这些数据的类TextDisplay,BarGrahpDisplay和PieChartDisplay。分别以文本,柱状图,饼图来显示数据。我们希望设计的系统是这样的,BankStatementData对象可以通知那些显示数组的对象,并且希望主题类与观察者类之间是松散耦合的。

     观察者设计模式提倡一个主题对象和观察者对象之间的松散耦合----当主题对象发生改变的时候,它通知观察器。当得到主题对象的通知时,观察器对象发生改变以响应主题对象的状态变化。在上面的例子中,BankStatementData对象是主题对象,显示数据的三个对象是观察器。一个主题对象可以通知若干个观察器。因此主题对象与观察器之间具有一对多的关系。

意图:

     在对象之间定义一个一对多的依赖。当一个对象发生变化的时候,它会通知所有依赖它的对象,并且这些依赖它的对象自动更新。

动机:

     这个模式中两个关键的对象是主题和观察者。一个主题可能有很多依赖它的观察者。当主题的状态发生变化时,必须通知所有的依赖它的观察者。所为回应,每个观察者都会通知主题以同步自己与主题的状态。

实现:

     一个定义观察者接口的抽象类:

class Subject;

class Observer {

public:

     virtual ~Observer();

     virtual void Update(Subject * theChangedSubject) = 0;

protected:

     Observer();

};

     一个定义主题接口的抽象类:

class Subject {

public:

     virtual ~Subject();

     virtual void Attach(Observer *);

     virtual void Detach(Observer *);

     virtual void Notify();

protected:

     Subject();

private:

     List<Observer *> *_observers;

};

void Subject::Attach(Observer *o) {

     _observers->Append(o);

}

void Subject::Detach(Observer *o){

     _observers->Remove(o);

}

void Subject::Notify(){   //当this发生变化时,它会通知所有依赖它的观察者

     ListIterator<Observer*> i(_observers);

     for(i.First(); !i.IsDone(); i.Next()){

          i.CurrentItem()->Update(this);

     }

};

一个具体的Subject类:

class ClockTimer : public Subject {

public:

     ClockTimer();

    

     virtual int GetHour();

     virtual int GetMinute();

     virtual int GetSecond();

     void Tick();   // updates the ClockTimer's internal state and calls Notify to inform observers of the change.

};

void ClockTimer::Tick() {

     //update internal time-keeping state

     //...

     Notify();

}

class DigitalClock : public Widget, public Observer {

public:

     DigitalClock(ClockTimer*);

     virtual ~DigitalClock();

     virutal void Update(Subject*); //overrides Observer operation

     virtual void Draw(); // overrides Widgets Operation, defines how to draw the digital clock

private:

     ClockTimer *_subject;   //具体Observer类持有一个具体Subject类的对象

};

DigitalClock::DigitalClock(ClockTimer *s) {

     _subject = s;

     _subject->Attach(this);

}

DigitalClock::DigitalClock(ClockTimer *s) {

     _subject->Detach(this);

}

void DigitalClock::Update(Subject * theChangedSubject) {

     if(theChangedSubject == _subject){

          Draw();

     }

}

void DigitalClock::Draw() {

     //draw the digital clock

}

另一个Observer具体类的定义

class AnalogClock : public Widget, public Observer {

public:

     AnalogClock(ClockTimer *) ;  //用一个具体主题类的对象来构造具体观察者类

     virtual void Update(Subject*);

     virtual void Draw();

private:

     ClockTimer * _subject;

};

主函数中的代码:

创建两个不同的Observer具体类对象和一个Subject具体类对象。用来显示一致的时间。

ClockTimer * timer = new ClockTimer();

AnalogClock * analogClock = new AnalogClock(timer);

DigitalClock* digitalClock = new DigitalClock(timer);

这样, 当timer变化时,它的值会在analogClock和digitalClock上显示出来。

原文地址:https://www.cnblogs.com/afreethinker/p/3274563.html