设计模式之观察者模式

来源:互联网 发布:图片加白边是什么软件 编辑:程序博客网 时间:2024/06/15 14:49

简介

  • 定义了一种一对多的依赖关系, 即当一个对象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与观察者双方解除耦合, 让双方都依赖与抽象而不是具体; 使得两端的变化都不会改动另一方;
0 0