zoukankan      html  css  js  c++  java
  • 观察者模式

    【1】什么是观察者模式?

    观察者模式,定义一种一对多的依赖关系,多个观察者对象同时监听某一个主题对象。

    当这个主题对象状态上发生变化时,会通知所有观察者对象,他们能够自动更新自己,随主题对象状态改变做出对应的行为表现。

    【2】观察者模式代码示例:

    代码示例如下:

      1 #include <iostream>
      2 #include <string>
      3 #include <list>
      4 using namespace std;
      5 
      6 class Observer;
      7 
      8 // 管理观察者的基类
      9 class Subject
     10 {
     11 public:
     12     string action;   // 主题名称
     13 protected:
     14     list<Observer*> observers;  // 观察者的容器
     15 
     16 public:
     17     virtual void attach(Observer*) = 0;
     18     virtual void detach(Observer*) = 0;
     19     virtual void notify() = 0;
     20 };
     21 
     22 // 观察者基类
     23 class Observer
     24 {
     25 protected:
     26     string name;
     27     Subject *sub;
     28 
     29 public:
     30     Observer(string name, Subject *sub)
     31     {
     32         this->name = name;
     33         this->sub = sub;
     34     }
     35     string getName()
     36     {
     37         return name;
     38     }
     39 
     40     virtual void update() = 0;
     41 };
     42 
     43 // 炒股票(观察者其一)
     44 class StockObserver : public Observer
     45 {
     46 public:
     47     StockObserver(string name, Subject *sub) : Observer(name, sub)
     48     {}
     49 
     50     void update();
     51 };
     52 
     53 void StockObserver::update()
     54 {
     55     cout << name << " 收到消息:" << sub->action << endl;
     56     if (sub->action == "梁所长来了!")
     57     {
     58         cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
     59     }
     60 }
     61 
     62 // 看NBA比赛(观察者其一)
     63 class NBAObserver : public Observer
     64 {
     65 public:
     66     NBAObserver(string name, Subject *sub) : Observer(name, sub)
     67     {}
     68     void update();
     69 };
     70 
     71 void NBAObserver::update()
     72 {
     73     cout << name << " 收到消息:" << sub->action << endl;
     74     if (sub->action == "梁所长来了!")
     75     {
     76         cout << "我马上关闭NBA,装做很认真工作的样子!" << endl;
     77     }
     78 }
     79 
     80 // 玩游戏(观察者其一)
     81 class GameObserver : public Observer
     82 {
     83 public:
     84     GameObserver(string name, Subject *sub) : Observer(name, sub)
     85     {}
     86 
     87     void update();
     88 };
     89 
     90 void GameObserver::update()
     91 {
     92     cout << name << " 收到消息:" << sub->action << endl;
     93     if (sub->action == "梁所长来了!")
     94     {
     95         cout << "我马上退出游戏,装做很认真工作的样子!" << endl;
     96     }
     97 }
     98 
     99 // 管理观察者的实现类(作为被观察者)
    100 class Secretary : public Subject
    101 {
    102 public:
    103     void attach(Observer *observer)
    104     {
    105         cout << "add: " << observer->getName() << endl;
    106         observers.push_back(observer);
    107     }
    108 
    109     void detach(Observer *observer)
    110     {
    111         list<Observer *>::iterator iter = observers.begin();
    112         while (iter != observers.end())
    113         {
    114             if ((*iter) == observer)
    115             {
    116                 cout << "erase: " << observer->getName() << endl;
    117                 observers.erase(iter++);
    118             }
    119             else
    120             {
    121                 ++iter;
    122             }
    123         }
    124     }
    125 
    126     void notify()
    127     {
    128         list<Observer *>::iterator iter = observers.begin();
    129         while (iter != observers.end())
    130         {
    131             (*iter)->update();
    132             ++iter;
    133         }
    134     }
    135 };
    136 
    137 
    138 void main()
    139 {
    140     Subject *pDwq = new Secretary();  // 主题对象,作为被观察者
    141 
    142     Observer *pXs = new NBAObserver("xiaoshuai", pDwq);  // 小帅,作为观察者(监听者)
    143     Observer *pZy = new GameObserver("zhuoyue", pDwq);  // 卓越,作为观察者(监听者)
    144     Observer *pLm = new StockObserver("liming", pDwq); // 李明,作为观察者(监听者)
    145 
    146     // 绑定观察者与被观察者
    147     cout << "登记监听者: " << endl;
    148     pDwq->attach(pXs);
    149     pDwq->attach(pZy);
    150     pDwq->attach(pLm);
    151 
    152     // 测试广播动作
    153     cout << endl << "测试广播动作效果: " << endl;
    154     cout << "发出动作1效果:去吃饭了!" << endl;
    155     pDwq->action = "去吃饭了!";
    156     pDwq->notify();
    157 
    158     cout << endl << "发出动作2效果:梁所长来了!" << endl;
    159     pDwq->action = "梁所长来了!";
    160     pDwq->notify();
    161 
    162     // 解除绑定监听
    163     cout << endl << "解除监听者: " << endl;
    164     pDwq->detach(pLm);
    165     pDwq->detach(pZy);
    166     pDwq->detach(pXs);
    167 
    168     delete pDwq;
    169     delete pXs;
    170     delete pZy;
    171     delete pLm;
    172 
    173     system("pause");
    174 }
    175 
    176 // run out:
    177 /*
    178 登记监听者:
    179 add: xiaoshuai
    180 add: zhuoyue
    181 add: liming
    182 
    183 测试广播动作效果:
    184 发出动作1效果:去吃饭了!
    185 xiaoshuai 收到消息:去吃饭了!
    186 zhuoyue 收到消息:去吃饭了!
    187 liming 收到消息:去吃饭了!
    188 
    189 发出动作2效果:梁所长来了!
    190 xiaoshuai 收到消息:梁所长来了!
    191 我马上关闭NBA,装做很认真工作的样子!
    192 zhuoyue 收到消息:梁所长来了!
    193 我马上退出游戏,装做很认真工作的样子!
    194 liming 收到消息:梁所长来了!
    195 我马上关闭股票,装做很认真工作的样子!
    196 
    197 解除监听者:
    198 erase: liming
    199 erase: zhuoyue
    200 erase: xiaoshuai
    201 请按任意键继续. . .

     【3】观察者模式的优缺点

    观察者模式的效果有以下的优点:

    第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。

      被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。

      被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

      由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

    第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。

    观察者模式有下面的缺点:

    第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

    第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

    第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

    Good  Good  Study, Day  Day  Up.

    顺序   选择   循环   总结

  • 相关阅读:
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
    SharePoint 打开文档附件不弹出提示框
    SharePoint2010 安装时报“未能启动数据库服务 MSSQL$Sharepoint"解决办法
    常见问题
    sharepoint 关于pdf格式在线打开
    ASP.NET 2.0 连接Sql Server 2005报错 [DBNETLIB][ConnectionOpen (Invalid Instance()).]无效的连线。
    <转>SQL Server 2008 R2十大新特性解析
    windows查看端口占用情况
    SQL Server适用脚本收集一
    信息系统中用户的域AD认证功能
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3946750.html
Copyright © 2011-2022 走看看