这是一个行为型设计模式,是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上显示出来。