观察者模式

来源:互联网 发布:java小球下落 编辑:程序博客网 时间:2024/06/14 10:27

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

观察者模式的应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。


抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。

抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。

具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。

具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。      


c++代码实现:

定义虚基类Subject与Observer

Subject类中需要保存所有它可以通知的对象,对象可用list存储,类型为Observer*类型,这样每次添加一个派生出的实际被观察角色对象时,相当于基类指针指向派生类对象,各个派生类对收到通知的接口各自实现,最后在通知时利用多态性质可以各自执行自己的操作。另外还需要提供添加对象,删除对象,以及通知的接口。

Observer类当做一个抽象类,只需要定义一个纯虚函数virtual void update()=0;即可。各个派生类对它重新实现后,即可在通知时做出不同的反应

ConcretSubject相当于秘书一般对Subject类的各个操作具体实现,并可以自己添加一些特有的功能,如通知某一个对象,通知某一组对象等等,此外,发送者还可以有自己的状态,在发送消息之前,对状态做修改后,各个响应操作里可以根据这个状态来做相应的操作。但是这时候需要思考一个问题,pConcretSubObj对象给ConcretObserver发送消息时,观察者知道是谁发送的吗?答案肯定是不知道的,既然不知道,那这个pConcreSubObj的状态又从何得知呢?所以可以在Observer类的成员变量中加入一个Subject 对象,在建立完一个ConCretSubject对象后再建立各个ConcretObserver对象时用前面的ConcretSubject对象来初始化Observer类中的这个Subject对象,这样ConcretSubject对象在收到通知时即可通过查看成员变量中的Subject对象的状态来做出反应。


这样便做到了一个消息发送多个对象,而消息对象同时也知道发送者是谁,根据状态来做出反应的需求。

下面给出c++代码实现

  #include <iostream>#include<list>#include<string>using namespace std;//观察者基类class Subject;class Observer{protected:Subject *sub;public:Observer(Subject *obj) { sub = obj; }virtual void update() = 0;};//实际的一个学生类观察者class Student:public Observer{public:Student(Subject *obj):Observer(obj) {}void update();};//实际的一个老师类观察者class Teacher :public Observer{public:Teacher(Subject *obj):Observer(obj) {}void update();};//对象类基类,提供注册和删除观察者对象的接口class Subject{protected:list<Observer*>m_obs;public:string m_action;virtual void Attach(Observer *) = 0;virtual void Detach(Observer *) = 0;virtual void Notify() = 0;//string Action() { return m_action; }};//将有关状态存入各ConcreteObserver对象;//当它的状态发生改变时,向它的各个观察者发出通知class ConcretSubject :public Subject{public:ConcretSubject() {}void Attach(Observer *pobj) { m_obs.push_back(pobj); }void Detach(Observer *obj) { m_obs.remove(obj); }
      //通知全部对象

  void Notify(){for (auto p : m_obs)p->update();}   
     //通知单个某一个对象
    void Nofity(Observer *obj)
    {
        bool bExist = false;
        for (auto &p : m_obs)
            if (obj == p)
                bExist = true;
        if (bExist)
            obj->update();
        else
            cout << "没有此对象" << endl;
    }void Student::update(){cout << "学生收到消息!"<<endl; if (sub->m_action == "下课了")cout << "学生很开心" << endl;}void Teacher::update(){cout << "老师收到消息"<<endl;if (sub->m_action == "下课了")cout << "老师也很开心" << endl;}int main(){Subject *obj=new ConcretSubject;Student *stu = new Student(obj);Teacher *tea = new Teacher(obj);obj->Attach(stu);obj->Attach(tea);obj->Notify();cout << endl;obj->m_action="下课了";obj->Notify();system("pause");}

执行结果如下









原创粉丝点击