行为型模式--观察者

1、意图

  定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

2、结构

 

 3、参与者

  Subect:目标。目标知道它的观察者。可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口;

  Observer:观察者。为那些在目标发生改变时需获得通知的对象定义一个更新接口;

  ConcreteSubject:具体目标。将有关状态存入各ConcreteObserver对象;当它的状态发生改变时,向它的各个观察者发出通知;

  ConcreteObserver:具体观察者。维护一个指向ConcreteSubject对象的引用;存储有关状态,这些状态应与目标的状态保持一致;实现Observer的更新接口以使自身状态与目标的状态保持一致。

4、适用性

  符合以下情况之一可使用观察者模式:

  当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用;

  当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变;

  当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的;

5、代码示例

class Subject;
class Observer 
{
public:
    virtual ~Observer(); 
    virtual void Update(Subject* thechangedsubject)= 0; 
protected:
    Observer();
};

// 支持一个观察者有多个目标。当观察者观察多个目标时,作为参数传递给Update操作的目标让观察者可以判定是哪一个目标发生了改变。
// 类似地,一个抽象类定义了Subject接口:
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 ()
{
    ListIterator<Observer*> i(_observers);
    for (i.First(); !i.IsDone(); i.Next ())
    {
        i.CurrentItem()->Update(this);
    }
}
// ClockTimer是一个用于存储和维护一天时间的具体目标。它每秒钟通知一次它的观察者。
// ClockTimer提供了一个接口用于取出单个的时间单位如小时,分钟,和秒。
class clockTimer : public Subject
{
public:
    clockTimer(); 
    virtual int GetHour(); 
    virtual int GetMinute(); 
    virtual int GetSecond(); 
    void Tick();
};

// Tick操作由一个内部计时器以固定的时间间隔调用,从而提供一个精确的时间基准。
// Tick更新ClockTimer的内部状态并调用Notify通知观察者:
void clockTimer::Tick ()
{
    // update internal time-keeping state
    // ...
    Notify();
}
// 现在我们可以定义一个DigitalClock类来显示时间。它从一个用户界面工具箱提供的Widget类继承了它的图形功能。
// 通过继承Observer,Observer接口被融入DigitalClock的接口。
class Digitalclock : public Widget, public Observer
{
public:
    Digitalclock(ClockTimer*); 
    virtual ~Digitalclock(); 
    virtual void Update(Subject*);
    // overrides observer operation

    virtual void Draw();        
    // overrides widget operation;
    // defines how to draw the digital clock 
private:
    clockTimer* _subject;
}; 

Digitalclock::Digitalclock (ClockTimer* s)
{
    _subject = s;
    _subject->Attach(this); 
}
Digitalclock::~Digitalclock ()
{
    _subject->Detach(this);
}

// 在Update操作画出时钟图形之前,它进行检查,以保证发出通知的目标是该时钟的目标
void Digitalclock::Update (Subject* thechangedSubject)
{
    if (thechangedSubject == _subject)
    {
        Draw();
    }
}

void Digitalclock::Draw ()
{
    // get the new values from the subject 
    int hour =_subject->GetHour(); 
    int minute =_subject->GetMinute();
    // etc.
    // draw the digital clock
}
// 一个AnalogClock可用相同的方法定义。
class Analogclock : public Widget, public observer
{
public:
    Analogclock(ClockTimer*); 
    virtual void Update(Subject*); 
    virtual void Draw();
    // ...
};

// 下面的代码创建一个AnalogClock和一个DigitalClock,它们总是显示相同时间
// 一旦timer走动,两个时钟都会被更新并正确地重新显示。
ClockTimer* timer = new ClockTimer; 
Analogclock* analogclock = new Analogclock(timer); 
Digitalclock* digitalclock = new Digitalclock(timer);

6、总结

  观察者模式定义了对象间一种一对多的依赖关系,当一个对象发生改变时,所有依赖该对象的其余对象都能得到通知并做相应处理。目标发送通知,观察者接收通知。

  目标与观察者之间实现了松耦合。

  

posted @ 2022-05-04 16:35  流翎  阅读(43)  评论(0)    收藏  举报