Observer

以前学习MFC的时候,在MDI框架下,经常会用到CDocument::UpdateAllViews(),然后在CView::Update()里面添加相应的代码。这样做的结果是当其中一个view的内容变化了,那么可以使其他view也作出相应的调整。知道现在才意识到原来这就是Observer模式。

Observer模式的核心其实就是定义一个一对多(one to many)的映射关系,这些对象之间可以相互照应,当一个的内容发生变化时,其他的对象可以作出相应的调整,当然,也可以不调整,要是你愿意。

Observer模式的结构如下:

图中,Subject提供对Observer注册、注销和通知的方法,当需要通知时,Subject::Notify()对所有已注册的Observer进行通知,然后Observer::Update()方法中,你就可以做你需要的事情了。

大概代码如下:

class Observer;

class Subject
{
public:
    virtual void Add(Observer* pObserver) = 0;
    virtual void Remove(Observer* pObserver) = 0;
    virtual void Notify(Observer* pObserver = NULL) = 0;
};

class ConcreteSubject : public Subject
{
public:
    ConcreteSubject();
    ~ConcreteSubject();

public:
    void Add(Observer* pObserver);
    void Remove(Observer* pObserver);
    void Notify(Observer* pObserver = NULL);

public:
    void SetData(int iCnt, int iTotal);
    int GetCount();
    int GetTotal();

private:
    void DestroyList();

private:
    list<Observer*>* m_pList;
    int m_iCnt;
    int m_iTotal;
};

class Observer
{
public:
    virtual void Update(Subject* pSubject, Observer* pObserver) = 0;
};

class ConcreteObserverA : public Observer
{
public:
    ConcreteObserverA(Subject* pSub);
    ~ConcreteObserverA();

public:
    void Update(Subject* pSubject, Observer* pObserver);

private:
    Subject* m_pSub;
};

class ConcreteObserverB : public Observer
{
public:
    ConcreteObserverB(Subject* pSub);
    ~ConcreteObserverB();

public:
    void Update(Subject* pSubject, Observer* pObserver);

private:
    Subject* m_pSub;
};

//
//        ConcreteSubject

ConcreteSubject::ConcreteSubject() : m_iCnt(0), m_iTotal(0)
{
    m_pList = new list<Observer*>;
}

ConcreteSubject::~ConcreteSubject()
{
    DestroyList();

    delete m_pList;
}

void ConcreteSubject::DestroyList()
{
}

void ConcreteSubject::Add(Observer* pObserver)
{
    m_pList->push_back(pObserver);
}

void ConcreteSubject::Remove(Observer* pObserver)
{
    if(pObserver){
        m_pList->remove(pObserver);
 }
}

void ConcreteSubject::Notify(Observer* pObserver /* = NULL */)
{
    list<Observer*>::iterator iter = m_pList->begin();

    for(; iter != m_pList->end(); iter++){
         (*iter)->Update(this, pObserver);
    }
}

void ConcreteSubject::SetData(int iCnt, int iTotal)
{
    m_iCnt = iCnt;
    m_iTotal = iTotal;

    Notify();
}

int ConcreteSubject::GetCount()
{
    return m_iCnt;
}

int ConcreteSubject::GetTotal()
{
    return m_iTotal;
}

//
//      ConcreteObserverA
ConcreteObserverA::ConcreteObserverA(Subject* pSub) : m_pSub(pSub)
{
     m_pSub->Add(this);
}

ConcreteObserverA::~ConcreteObserverA()
{
    m_pSub->Remove(this);
}

void ConcreteObserverA::Update(Subject* pSubject, Observer* pObserver)
{
    if(pObserver == this){
       
return;
    }

    ConcreteSubject* pSub = (ConcreteSubject*)pSubject;

    cout << "ConcreteObserverA::Update() has been called" << endl;
    cout << "the current count is " << pSub->GetCount() << ", the total count is " << pSub->GetTotal() << endl;
}

//
//      ConcreteObserverB
ConcreteObserverB::ConcreteObserverB(Subject* pSub) : m_pSub(pSub)
{
    m_pSub->Add(this);
}

ConcreteObserverB::~ConcreteObserverB()
{
    m_pSub->Remove(this);
}

void ConcreteObserverB::Update(Subject* pSubject, Observer* pObserver)
{
    if(pObserver == this){
        return;
    }

    ConcreteSubject* pSub = (ConcreteSubject*)pSubject;

    cout << "ConcreteObserverB::Update() has been called" << endl;
    cout << "(count, total) : (" << pSub->GetCount() << ", " << pSub->GetTotal() << "), " ;
    cout << "It is " << pSub->GetCount() * 100 / pSub->GetTotal() << "%" << endl;
}

测试代码

void main()
{
    ConcreteSubject subject;
    ConcreteObserverA a(&subject);
    ConcreteObserverB b(&subject);

    subject.SetData(10, 100);
    subject.SetData(20, 100);
}


输出结果:
ConcreteObserverA::Update() has been called
the current count is 10, the total count is 100
ConcreteObserverB::Update() has been called
(count, total) : (10, 100), It is 10%
ConcreteObserverA::Update() has been called
the current count is 20, the total count is 100
ConcreteObserverB::Update() has been called
(count, total) : (20, 100), It is 20%
可以看出,Subject维护着一个Observer的列表,当有通知时,Subject::Notify()遍历列表,向每一个Observer发送通知。

Observer模式应用很广泛,MFC框架、MVC框架等等都采用了Observer模式。举个例子:我们做了一个天气预报系统,当数据库中的数据发生变化时,我们就可以遍历列表来通知所有的观察者,但是我们并不需要关心观察者是通过电视还是收音机还是广播来接受消息的,我们只要确保它能够接受到数据更新消息就行。如果观察者不需要我们的更新消息了,我们只需要从列表中把它Remove掉就ok,也就是说,观察者他已经把它那可爱的收音机关掉了,呵呵。

Observer模式定义的是一个一对多的对象间关系,他是对象间松耦合,每个对象并不需要知道其他对象的细节,而只需要保证他们能够得到数据更新的消息,仅此而已。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值