设计模式-观察者模式

设计模式 | 观察者模式

libdash播放器使用的就是观察者模式的设计方式!

什么是观察者模式:

  • 观察者模式软件设计模式的一种。
  • 在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知
  • 这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来 实时事件处理 系统。

使用动机:

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

使用场景:

  • 使对象封装为独立的改变和使用;
  • 一个对象改变同时需要改变其它对象,而不知道具体有多少对象需要改变;
  • 不希望对象是紧耦合的;

结构

Observer Pattern

  • Subject:抽象目标,知道它的观察者,提供注册和删除观察者对象的接口
  • Observer:抽象观察者,为那些在目标发生改变时需获得通知的对象定义一个更新接口
  • ConcreteSubject:具体目标,存储对象状态,状态改变时,向各个观察者发出通知
  • ConcreteObserver:具体观察者,维护一个指向ConcreteSubject对象的引用,存储有关状态,实现更新接口update,使自身状态与目标的状态保持一致

优缺点:

  • 目标和观察者之间松耦合
  • 支持广播通信:Subject发送的通知不需要指定它的接受者。通知被自动广播给所有已向该目标对象登记的有关对象。
  • 意外的更新:看似无害的操作可能会引起观察者错误的更新。

示例代码:

该部分转载自作者:一去丶二三里

创建抽象主题:

提供关于注册、注销、通知观察者的接口:

// subject.h
#ifndef SUBJECT_H
#define SUBJECT_H

class IObserver;

// 抽象主题
class ISubject
{
public:
    virtual void Attach(IObserver *) = 0;  // 注册观察者
    virtual void Detach(IObserver *) = 0;  // 注销观察者
    virtual void Notify() = 0;  // 通知观察者
};

#endif // SUBJECT_H

创建具体主题:

抽象主题的具体实现,用于管理所有的观察者:

// concrete_subject.h
#ifndef CONCRETE_SUBJECT_H
#define CONCRETE_SUBJECT_H

#include "subject.h"
#include "observer.h"
#include <iostream>
#include <list>

using namespace std;

// 具体主题
class ConcreteSubject : public ISubject
{
public:
    ConcreteSubject() { m_fPrice = 10.0; }

    void SetPrice(float price) {
        m_fPrice = price;
    }

    void Attach(IObserver *observer) {
        m_observers.push_back(observer);
    }

    void Detach(IObserver *observer) {
        m_observers.remove(observer);
    }

    void Notify() {
        list<IObserver *>::iterator it = m_observers.begin();
        while (it != m_observers.end()) {
            (*it)->Update(m_fPrice);
            ++it;
        }
    }

private:
    list<IObserver *> m_observers;  // 观察者列表
    float m_fPrice;  // 价格
};

#endif // CONCRETE_SUBJECT_H

创建抽象观察者:

提供一个 Update() 接口,用于更新价格:

// observer.h
#ifndef OBSERVER_H
#define OBSERVER_H

// 抽象观察者
class IObserver
{
public:
    virtual void Update(float price) = 0;  // 更新价格
};

#endif // OBSERVER_H

创建具体观察者:

抽象观察者的具体实现,当接收到通知后,调整对应的价格:

// concrete_observer.h
#ifndef CONCRETE_OBSERVER_H
#define CONCRETE_OBSERVER_H

#include "observer.h"
#include <iostream>
#include <string>

using namespace std;

// 具体观察者
class ConcreteObserver : public IObserver
{
public:
    ConcreteObserver(string name) { m_strName = name; }

    void Update(float price) {
        cout << m_strName << " - price: " << price << "\n";
    }

private:
     string m_strName;  // 名字
};

#endif // CONCRETE_OBSERVER_H

创建客户端:

创建主题以及对应的观察者,并添加观察者并更新价格:

// main.cpp
#include "concrete_subject.h"
#include "concrete_observer.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif

int main()
{
    // 创建主题、观察者
    ConcreteSubject *pSubject = new ConcreteSubject();
    IObserver *pObserver1 = new ConcreteObserver("Jack Ma");
    IObserver *pObserver2 = new ConcreteObserver("Pony");

    // 注册观察者
    pSubject->Attach(pObserver1);
    pSubject->Attach(pObserver2);

    // 更改价格,并通知观察者
    pSubject->SetPrice(12.5);
    pSubject->Notify();

    // 注销观察者
    pSubject->Detach(pObserver2);
    // 再次更改状态,并通知观察者
    pSubject->SetPrice(15.0);
    pSubject->Notify();

    SAFE_DELETE(pObserver1);
    SAFE_DELETE(pObserver2);
    SAFE_DELETE(pSubject);

    getchar();

    return 0;
}
运行结果:
Jack Ma - price: 12.5 
Pony - price: 12.5 
Jack Ma - price: 15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值