设计模式学习(行为型模式)--观察者模式

定义

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

适用情况

当一个对象的改变需要改变其他对象的时候,且它不知道具体有多少对象有待改变。

使用情况举例

场景来自《大话设计模式》。
办公室同事沉迷于炒股,上班时间也在看股票,老板在办公室时会被批评,于是拜托秘书在老板回来时通知一下,关闭炒股页面,继续工作,避免被老板发现。同样的,还有看NBA和打游戏的同事。基于此场景,构建UML类图,并编写相关代码。

UML类图

在这里插入图片描述

这里用C++实现,因此只有抽象类,没有接口。

实现代码

抽象目标类

class Subject
{
public:
    Subject();
    virtual void registerListenner(Observer *observer) = 0;
    virtual void removeListenner(Observer *observer) = 0;
    virtual void notify() = 0;
};

秘书类(具体目标类)

#include "secretary.h"

Secretary::Secretary()
{
    fellowList.clear();
    this->action = false;
}

//添加需要通知的同事
void Secretary::registerListenner(Observer *observer)
{
    fellowList.push_back(observer);
}

//去除不再需要通知的同事
void Secretary::removeListenner(Observer *observer)
{
    for (vector<Observer*>::iterator iter=fellowList.begin(); iter!=fellowList.end(); iter++)
    {
        if( *iter == observer)
        {
            fellowList.erase(iter);
            break;
        }
    }
}

//通知同事
void Secretary::notify()
{
    for (vector<Observer*>::iterator iter=fellowList.begin(); iter!=fellowList.end(); iter++)
    {
        if(action)
        {
           (*iter)->onBossComing(SECRETARY_MESSAGE_COME);
        }
        else
        {
            (*iter)->onBossOut(SECRETARY_MESSAGE_OUT);
        }
    }
}

//设置当前老板位置,true表示回来了,false表示走了
void Secretary::setAction(bool bossAction)
{
    this->action = bossAction;
    notify();
}

另一个具体目标类代码类似

玩游戏的同事类(具体观察者类)

#include "gameobserver.h"

gameObserver::gameObserver()
{

}

gameObserver::gameObserver(string name)
{
    this->name = name;
}

//老板来了
void gameObserver::onBossComing(string bossMessage)
{
    cout<<bossMessage<<"-->";
    stopGame();
}

//老板走了
void gameObserver::onBossOut(string bossMessage)
{
    cout<<bossMessage<<"-->";
    doGame();
}

void gameObserver::stopGame()
{
    cout<<name<<"停止玩游戏,开始工作"<<endl;
}

void gameObserver::doGame()
{
    cout<<name<<"继续玩游戏"<<endl;
}

另外两个具体观察者类代码类似

主函数

	Boss boss;
    Secretary secretary;
    gameObserver gameFellow("张三");
    stockObserver stockFellow("李四");
    NBAObserver nbaFellow("王五");

    //监听老板
    boss.registerListenner(&gameFellow);
    boss.registerListenner(&stockFellow);
    boss.registerListenner(&nbaFellow);

    //监听秘书
    secretary.registerListenner(&gameFellow);
    secretary.registerListenner(&stockFellow);
    secretary.registerListenner(&nbaFellow);

    //老板回来了
    boss.setAction(true);
    cout<<endl;

    //老板走了
    boss.setAction(false);
    cout<<endl;

    //秘书发现老板回来了
    secretary.setAction(true);
    cout<<endl;

    //秘书发现老板走了
    secretary.setAction(false);
    cout<<endl;

    //老板允许上班看股票,移除看股票同事对老板的监听
    cout<<"上班时间允许看股票了"<<endl;
    cout<<endl;
    boss.removeListenner(&stockFellow);
    boss.setAction(true);
    cout<<endl;
    boss.setAction(false);
    cout<<endl;

    //上班允许看比赛,移除看比赛同事对秘书的监听
    cout<<"上班时间可以看比赛了"<<endl;
    cout<<endl;
    secretary.removeListenner(&nbaFellow);
    secretary.setAction(true);
    cout<<endl;
    secretary.setAction(false);
    cout<<endl;

运行效果

我回来了-->张三停止玩游戏,开始工作
我回来了-->李四停止看股票,开始工作
我回来了-->王五停止看NBA比赛,开始工作

我走了-->张三继续玩游戏
我走了-->李四继续看股票
我走了-->王五继续看NBA比赛

老板回来了-->张三停止玩游戏,开始工作
老板回来了-->李四停止看股票,开始工作
老板回来了-->王五停止看NBA比赛,开始工作

老板走了-->张三继续玩游戏
老板走了-->李四继续看股票
老板走了-->王五继续看NBA比赛

上班时间允许看股票了

我回来了-->张三停止玩游戏,开始工作
我回来了-->王五停止看NBA比赛,开始工作

我走了-->张三继续玩游戏
我走了-->王五继续看NBA比赛

上班时间可以看比赛了

老板回来了-->张三停止玩游戏,开始工作
老板回来了-->李四停止看股票,开始工作

老板走了-->张三继续玩游戏
老板走了-->李四继续看股票

总结

观察者模式优点

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
  2. 目标与观察者之间建立了一套触发机制。

观察者模式缺点

  1. 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
  2. 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率

参考资料

  1. http://c.biancheng.net/view/1390.html
  2. 《大话设计模式》P123-P140
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值