关闭

观察者模式

129人阅读 评论(0) 收藏 举报
分类:

定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,而观察者只需注册主题后,就可以获取通知,若不想继续观察主题,让主题在观察者列表中删掉对应观察者就好了。

适用场景:1.当两个交互模块需要松耦合时;

  2.当一个对象的状态发生改变,需要通知其它对象做成相应动作。

组成:

Subject:定义发送通知的接口,以及注册和删除观察者。

Observe:定义观察者接收到通知后的状态更新接口。

ConcreteSubject:

1.在一个列表中存储注册了的观察者;

2.当状态发送改变时,通知观察者

ConcreteObserve:

1.在内部维护一个指向ConcreteSubject的指针或引用

2.存储有关状态,这些状态与主题状态应该一致

3.实现Observe的更新接口,使自身状态与主题的状态一致。

类图:


代码:


#include <cstdio>
#include <stack>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <list>
#include <functional>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <iomanip>
#include <cmath>
#include <time.h>
#define LL long long
using namespace std;

// 观察者,派生出具体观察者,实现当有通知时的动作
class observe
{
public:
        virtual void update()=0;
};

// 主题,当有状态变化时通知相关观察者。
class subject
{
public:
        virtual void registe(observe*)=0;
        virtual void remove(observe*)=0;
        virtual void notify()=0;
};

// 有新电影上映就发送通知
class cinema:public subject
{
private:
        list<observe*> objs;
        string newMovie;
public:
        void registe(observe *obj)
        {
                objs.push_back(obj);
        }
        void remove(observe *obj)
        {
                objs.remove(obj);
        }
        void notify()
        {
                for (auto it=objs.begin();it!=objs.end();it++)  {
                        (*it)->update();
                }
        }

        void haveNewMovie(string movie)
        {
                newMovie = movie;
                notify();
        }
        string getMovieName()
        {
                return newMovie;
        }
};

// student 接收到消息后的反应
class student:public observe
{
private:
        subject *sub;
public:
        student(subject *_sub):sub(_sub)
        {
                sub->registe(this);
        }
        void update()
        {
                cout<<"well, let us go to cinema and see "<< ((cinema*)sub)->getMovieName()<<endl;
        }
};

// teacher 接收到消息后的<span style="font-family: Arial, Helvetica, sans-serif;">反应</span>
class teacher:public observe
{
private:
        subject *sub;
public:
        teacher(subject *_sub):sub(_sub)
        {
                sub->registe(this);
        }
        void update()
        {
                cout<<"shit,those students will see "<< ((cinema*)sub)->getMovieName()<<endl;
        }
};


int main()
{
        cinema obs;
        student stu1(&obs);
        student stu2(&obs);
        teacher tea(&obs);

        obs.haveNewMovie("Harry Potter");
        obs.haveNewMovie("2012");

}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:45129次
    • 积分:1782
    • 等级:
    • 排名:千里之外
    • 原创:133篇
    • 转载:31篇
    • 译文:0篇
    • 评论:7条
    最新评论