【设计模式】之二十三种设计模式--观察者模式

观察者模式

也叫做发布订阅模式(Publish/subscribe)
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)

通用类图

被观察者抽象类
定义被观察者必须实现的职责,能够动态的增加、取消观察者,完成被观察者必须实现的职责:管理观察者并通知观察者
被观察者具体类
继承其抽象类,定义自己的业务逻辑,定义对哪些事件进行通知
观察者抽象类
观察者接收到消息后,对信息进行处理
观察者具体类
继承其抽象类,每个观察者收到信息后的处理不同,实现各自的逻辑

通用源码

//被观察者抽象类
class Subject {
public:
    //增加观察者
    void addObserver(Observer *ob) {
        sob.insert(ob);
    }
    //删除观察者
    void deleteObserver(Observer *ob) {
        sob.erase(ob);
    }
    //通知观察者
    void notifyObservers() {
        for(auto ob : sob) ob->updated();
    }
private:
    //定义观察数组
    set<Observer*> sob;
};
//被观察者具体类
class ConcreteSubject : public Subject {
public:
    void doSomething() {
        //do something
        Subject::notifyObservers();
    }
};
//观察者抽象类
class Observer {
public:
    //更新方法
    virtual void updated() = 0;
};
//观察者具体类
class ConcreteObserver : public Observer {
public:
    void updated() override {
        //收到消息,逻辑处理
    }
};

优点

观察者和被观察者之间是抽象耦合,观察者和被观察者都非常容易扩展
建立一套触发机制,一个事物的改变引起其他事物的变化

缺点

需要考虑开发效率和运行效率

使用场景

关联行为场景
事件多级触发场景
跨系统的消息交换场景

注意事项

广播链的问题
当一个对象既是观察者又是被观察者,会导致逻辑比较复杂,可维护性变差
异步处理问题
当观察者非常多的时候,异步处理,需要考虑线程安全和队列的问题

示例代码

#include <iostream>
#include <string>
#include <thread>
#include <unistd.h>
#include <set>

using namespace std;

class IHanFeiZi {
public:
    virtual void haveBreakfast() = 0;
    virtual void haveFun() = 0;
};

/*
//利用线程观察,耗费资源,降低效率
class HanFeiZi : public IHanFeiZi {
public:
    void haveBreakfast() override {
        cout << "HanFeiZi: have breakfast..." << endl;
        isHavingBreakfast = true;
    }
    void haveFun() override {
        cout << "HanFeiZi: have fun..." << endl;
        isHavingFun = true;
    }
    void setHavingBreakfast(bool b) {isHavingBreakfast = b;}
    bool getHavingBreakfast() {return isHavingBreakfast;}
    void setHavingFun(bool b) {isHavingFun = b;}
    bool getHavingFun() {return isHavingFun;}
private:
    bool isHavingBreakfast = false;
    bool isHavingFun = false;
};

class ILiSi {
public:
    virtual void update(string) = 0;
};

class LiSi : public ILiSi {
public:
    void update(string s) override {
        cout << "LiSi: report:" << endl;
        reportToQinShiHuang(s);
        cout << "LiSi: over" << endl;
    }
private:
    void reportToQinShiHuang(string s) {
        cout << s << endl;
    }
};

class Spy{
public:
    Spy(HanFeiZi &h, LiSi &l, string s):han(h), li(l), type(s) {
        thread t(bind(&Spy::run, this));
        t.detach();
    }
    void run() {
        while(r) {
            if(type == "breakfast") {
                if(han.getHavingBreakfast()) {
                    li.update("have breakfast");
                    han.setHavingBreakfast(false);
                }
            }else {
                if(han.getHavingFun()) {
                    li.update("have fun");
                    han.setHavingFun(false);
                }
            }
        }
    }
    void setRun(bool b) {
        r = b;
    }
private:
    bool r = true;
    HanFeiZi& han;
    LiSi& li;
    string type;
};
*/
//modify
class Observer {
public:
    virtual void update(string) = 0;
};

class Observable {
public:
    virtual void addObserver(Observer*) = 0;
    virtual void deleteObserver(Observer*) = 0;
    virtual void notifyObservers(string) = 0;
};

class HanFeiZi_t : public Observable, public IHanFeiZi {
public:
    void addObserver(Observer* ob) override {
        sob.insert(ob);
    }
    void deleteObserver(Observer* ob) override {
        sob.erase(ob);
    }
    void notifyObservers(string s) override {
        for(auto ob : sob) ob->update(s);
    }
    void haveBreakfast() override {
        cout << "HanFeiZi: have breakfast..." << endl;
        notifyObservers("have breakfast");
    }
    void haveFun() override {
        cout << "HanFeiZi: have fun..." << endl;
        notifyObservers("have fun");
    }
private:
    set<Observer*> sob;
};

class LiSi : public Observer {
public:
    void update(string s) override {
        cout << "LiSi: report:" << endl;
        reportToQinShiHuang(s);
        cout << "LiSi: over" << endl;
    }
private:
    void reportToQinShiHuang(string s) {
        cout << s << endl;
    }
};
class WangSi : public Observer {
public:
    void update(string s) override {
        cout << "WangSi: report:" << endl;
        reportToQinShiHuang(s);
        cout << "WangSi: over" << endl;
    }
private:
    void reportToQinShiHuang(string s) {
        cout << s << endl;
    }
};
class LiuSi : public Observer {
public:
    void update(string s) override {
        cout << "LiuSi: report:" << endl;
        reportToQinShiHuang(s);
        cout << "LiuSi: over" << endl;
    }
private:
    void reportToQinShiHuang(string s) {
        cout << s << endl;
    }
};

int main() {
    /*
    LiSi l;
    HanFeiZi h;
    string s1 = "fun";
    string s2 = "breakfast";
    Spy fun(h, l, s1);
    Spy breakfast(h, l, s2);
    cout << "fun begin" <<endl;
    h.haveFun();
    sleep(1);
    cout << "breakfast begin" << endl;
    h.haveBreakfast();
    sleep(1);
    fun.setRun(0);
    breakfast.setRun(0);
    cout << "spy end" << endl;
    */
    LiSi li;
    LiuSi liu;
    WangSi wang;
    HanFeiZi_t ht;
    ht.addObserver(&li);
    ht.addObserver(&liu);
    ht.addObserver(&wang);
    ht.haveBreakfast();
    ht.deleteObserver(&wang);
    ht.haveFun();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值