设计模式之观察者模式

简介
  • 定义了一种一对多的依赖关系, 即当一个对象subject改变时, 会通知所有与之关联的对象observer并自动更新;
  • 也叫发布-订阅publish-subscribe, 依赖Dependents;
  • 这些依赖的对象之间可能不知道对方的存在;
  • 当subject发生变化, observer会查询目标并更新状态;
适用
  • 当一个对象发生变化时希望通知另几个对象,但同时又不希望这些对象是紧密耦合;
结构
  • subject类要登记所有的observer,以通知它们, 而具体的observer则要保留想观察的subject的引用,以用来查阅subject的变化并更新;
  • observer观察多个subject是可能的, 此时就要扩展update()接口, 让observer知道是哪个suject发来的更新通知;
  • 也可以扩展observer的注册接口, 让observer注册为仅对特定的通知感兴趣, 这样不至于每次接受到通知就出更新状态, 而这个状态可能对该observer来说没有任何更新意义;
  • 当一个observer关注多个subject时, 如果采用简单的通知方式即subject每次更新就通知observer, 则很有可能会发生通知冗余的情况, 这时可以通过一个中间的对象:ChangeManager来管理subject的更新, 只有当subject全部跟新完后, 才会向observer发送更新通知, 这样就保证了observer只更新一次;
例子

小明和小梦正式走到一起后, 小明才发现原来相爱容易相处难, 为了将小梦留着身边,小明也是尽心尽力, 得对小梦的各种变化做出相应的应对; 比如哪天小梦不高兴了, 小明就不得不硬着头皮对小梦的各种情绪给予笑脸相迎, 而小梦心情好了那小明的春天就来了, 就可以向刚开始谈恋爱时一样各种调戏小梦了; 哪天小梦想吃零食了,小明立马会上淘宝购各种好吃的….
上面的例子就可以看成是小明订阅了小梦的需求, 并在小梦需求发生变化时立马做出相应的改变, 只有这样才能抱得美人归…

实现
class Observer;
// 抽象主题,这里表示情绪, 在主题类里添加了当前情绪的名字
class Mood
{
public:
    Mood():mood(""){}
    void Attach(Observer* obsvr) { mObsvr.insert(obsvr);}
    void Dettach(Observer* obsvr) {mObsvr.erase(obsvr);}
    virtual void Notify(string str) {};
    string GetMood() { return mood;}
protected:
    set<Observer*> mObsvr;
    void ChangeMood(string str)
    {
        mood = str;
        cout<<"xiaomeng become "<<mood<<endl;
    }
     string mood;
};
// 抽象观察者
class Observer
{
public:
    virtual void Updata() = 0;
    virtual void RegisteSubject(Mood* mood) = 0;
};
// 女朋友的情绪
class GirlFriendMood : public Mood
{
public:
    GirlFriendMood(string str)
    {
        mood = str;
        cout<<"xiaomeng feels "<<str<<" today!"<<endl;
    }
    void Notify(string str)
    {
        ChangeMood(str);
        for(set<Observer*>::iterator itr =  mObsvr.begin(); itr != mObsvr.end();++itr)
            (*itr)->Updata();
    }
};
// 男朋友时刻注意着女朋友的情绪变化
class BoyFriend:public Observer
{
public:
    BoyFriend(string name):mGirlMood(0),Boy(name){};
    virtual void Updata()
    {
        cout<<Boy<<"'s emotion become unstable,"<<Boy<<" need cooperate with xiaomeng!"<<endl;
        string str = mGirlMood->GetMood();
        cout<<Boy<<" know xiaomeng is "<<str<<endl;
    }
    virtual void RegisteSubject(Mood* mood)
    {
        mGirlMood = mood;
    }
private:
    Mood* mGirlMood;
    string Boy;
};
int main()
{
    Observer* xiaoming = new BoyFriend("xiaoming");
    Mood* xiaomeng = new GirlFriendMood("happy");
    xiaoming->RegisteSubject(xiaomeng);
    xiaomeng->Attach(xiaoming);
    xiaomeng->Notify("feels hot");
    return 0;
}
总结
  • 显然,这里的观察者可以是多个并添加到相应的subject的通知集合中即可;
  • 同时观察者也可以同事注意多个subject;
  • 该模式用于当一个对象改变需要同时改变其它对象的时候;
  • 且主题可以不知道有多少个对象需要通知; 该方法就是将subject与观察者双方解除耦合, 让双方都依赖与抽象而不是具体; 使得两端的变化都不会改动另一方;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值