观察者模式

定义:

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,在它的状态发生变化时,会通知所有的观察者,使它们自己能更新自己。

动机:

将一个系统设计成一系列相互协作的类有一个常见的副作用:需要维护相关对象之间的一致性。不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

观察者模式定义一种交互,即发布-订阅:

  • 一个对象当自身状态发生改变时,会发出通知,但是并不知道谁是他的接收者,但每个接收者都会接收到通知,这些接受者称为观察者。
  • 作为对通知的响应,每个观察者都将查询目标状态,然后改变自身的状态以和目标状态进行同步。

实例:Observer 的一个实例 Model/View/Control( MVC) 结构在系统开发架构设计中有着很重要的地位和意义, MVC实现了业务逻辑和表示层的解耦。在 MFC 中, Doc/View(文档视图结构)提供了实现 MVC 的框架结构。

使用场景:

  • 使对象封装为独立的改变和使用;
  • 一个对象改变同时需要改变其它对象,而不知道具体有多少对象需要改变;
  • 当一个抽象类型有两个方面,其中一方面依赖于另一方面,这时使用观察者模式可将这两者封装在独立的对象中使他们各自独立的改变和复用
  • 不希望对象是紧耦合的。

观察者模式所做的就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使各自的变化都不会影响另一边的变化。(依赖倒置原则的最佳体现)

观察者模式有下面的缺点

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

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

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

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

优点:

第一、观察者模式在通知者和观察者之间建立一个抽象的耦合。通知者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。通知者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

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

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


UML图:

抽象观察者角色Observer:为所有的具体观察者定义一个接口,在得到主题通知时更新自己
抽象通知者角色Subject:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
具体观察者角色ConcreteObserver:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
具体通知者角色ConcreteSubject:也就是一个具体的主题,在集体主题的内部状态改变时,给所有登记过的观察者发出通知。

#include <iostream>
#include <list>
using namespace std;

//抽象观察者
class Observer
{
public:
    virtual void Update(int) = 0;//观察者自己更新
};
//抽象通知者
class Subject
{
public:
    virtual void Attach(Observer *) = 0;//增加观察者
    virtual void Detach(Observer *) = 0;//减少观察者
    virtual void Notify() = 0;//通知观察者
};
//具体观察者
class ConcreteObserver : public Observer
{
public:
    ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){}

    void Update(int value)
    {
        cout << "ConcreteObserver get the update. New State:" << value << endl;
    }

private:
    Subject *m_pSubject;
};
//具体观察者2
class ConcreteObserver2 : public Observer
{
public:
    ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){}

    void Update(int value)
    {
        cout << "ConcreteObserver2 get the update. New State:" << value << endl;
    }
private:
    Subject *m_pSubject;
};
//具体通知者
class ConcreteSubject : public Subject
{
public:
    void Attach(Observer *pObserver);
    void Detach(Observer *pObserver);
    void Notify();

    void SetState(int state)
    {
        m_iState = state;
    }

private:
    list<Observer *> m_ObserverList;
    int m_iState;
};

void ConcreteSubject::Attach(Observer *pObserver)
{
    m_ObserverList.push_back(pObserver);
}

void ConcreteSubject::Detach(Observer *pObserver)
{
    m_ObserverList.remove(pObserver);
}

void ConcreteSubject::Notify()
{
    list<Observer *>::iterator it = m_ObserverList.begin();
    while (it != m_ObserverList.end())//通知每一个观察者
    {
        (*it)->Update(m_iState);//每一个观察者更新自己的状态
        ++it;
    }
}

int main()
{
    // Create Subject
    ConcreteSubject *pSubject = new ConcreteSubject();

    // Create Observer
    Observer *pObserver = new ConcreteObserver(pSubject);
    Observer *pObserver2 = new ConcreteObserver2(pSubject);

    // Change the state
    pSubject->SetState(2);

    // Register the observer
    pSubject->Attach(pObserver);
    pSubject->Attach(pObserver2);

    pSubject->Notify();

    // Unregister the observer
    pSubject->Detach(pObserver);

    pSubject->SetState(3);
    pSubject->Notify();

    delete pObserver;
    delete pObserver2;
    delete pSubject;

    return 0;
}

例2:

#include <iostream>
#include <string>
#include <list>
using namespace std;

class Observer;
//抽象通知者
class Subject
{
protected:
    list<Observer*> observers;
public:
    string action;
    virtual void attach(Observer*) = 0;
    virtual void detach(Observer*) = 0;
    virtual void notify() = 0;
};
//抽象观察者
class Observer
{
protected:
    string name;
    Subject *sub;
public:
    Observer(string name, Subject *sub)
    {
        this->name = name;
        this->sub = sub;
    }
    virtual void update() = 0;
};
//具体的观察者,看股票的
class StockObserver :public Observer
{
public:
    StockObserver(string name, Subject *sub) :Observer(name, sub){}
    void update();
};
//具体的观察者,看NBA的
class NBAObserver :public Observer
{
public:
    NBAObserver(string name, Subject *sub) :Observer(name, sub){}
    void update();
};

//具体通知者,秘书
class Secretary :public Subject
{
    void attach(Observer *observer)
    {
        observers.push_back(observer);
    }
    void detach(Observer *observer)
    {
        list<Observer *>::iterator iter = observers.begin();
        while (iter != observers.end())
        {
            if ((*iter) == observer)
            {
                observers.erase(iter);
            }
            ++iter;
        }
    }
    void notify()
    {
        list<Observer *>::iterator iter = observers.begin();
        while (iter != observers.end())
        {
            (*iter)->update();//观察者更新自己状态
            ++iter;
        }
    }
};

void StockObserver::update()
{
    cout << name << " 收到消息:" << sub->action << endl;
    if (sub->action == "梁所长来了!")
    {
        cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
    }
}

void NBAObserver::update()
{
    cout << name << " 收到消息:" << sub->action << endl;
    if (sub->action == "梁所长来了!")
    {
        cout << "我马上关闭NBA,装做很认真工作的样子!" << endl;
    }
}

int main()
{
    Subject *dwq=new Secretary();
    Observer *xs=new NBAObserver("xioashuai",dwq);//创建观察者
    Observer *zy=new NBAObserver("zouyue",dwq);
    Observer *lm=new StockObserver("limin",dwq);
    dwq->attach(xs);
    dwq->attach(zy);
    dwq->attach(lm);

    dwq->action="去吃饭了";
    dwq->notify();
    cout<<endl;
    dwq->action="梁所长来了!";
    dwq->notify();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值