【设计模式】观察者模式

什么是观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式。

它的作用是当一个对象的状态发生变化时,可以自己主动通知其它关联对象,自己主动刷新对象状态。

观察者模式的主要组成部分

  1. 主题(Subject):它是一个接口或者抽象类,定义了注册、注销和通知观察者的方法。
  2. 观察者(Observer):定义了观察者的接口,当被观察的对象状态发生变化时,观察者自身会收到通知。
  3. 具体主题(ConcreteSubject):实现了主题接口,并维护一个观察者列表。当状态发生改变时,调用通知方法来更新所有观察者。
  4. 具体观察者(ConcreteObserver):实现了观察者接口,并注册到主题。当具体目标状态发生变化时,自身会接到通知。

代码示例

下面的代码示例中:

  • Observer 是观察者的接口,所有具体观察者都需要实现这个接口中的 update 方法。
  • Subject 是主题的接口,定义了注册、注销和通知观察者的方法。
  • ConcreteSubject 是具体主题类,它维护了一个观察者列表,并在状态变化时通知所有观察者。
  • ConcreteObserver 是具体观察者类,它实现了 Observer 接口,并在 update 方法中定义了当收到通知时的具体行为。

在 main 函数中,我们创建了一个具体主题对象和两个观察者对象,将观察者注册到主题中,然后改变主题的状态。每次状态改变时,主题都会通知所有注册的观察者,观察者会更新自身状态并输出。最后,我们注销了一个观察者,并再次改变主题的状态,此时只有未注销的观察者会收到通知。

#include <iostream>
#include <list>
#include <memory>

// 观察者接口  (可用于派生多种观察者类)
class Observer {
public:
    virtual void update(int state) = 0;
    virtual ~Observer() = default;
};

// 主题接口  (可用于派生多种主题类)
class Subject {
public:
    virtual void attach(std::shared_ptr<Observer> observer) = 0;
    virtual void detach(std::shared_ptr<Observer> observer) = 0;
    virtual void notify() = 0;
    virtual ~Subject() = default;
};



// 具体主题类 (从Subject 类派生)
class ConcreteSubject : public Subject {
private:
    std::list<std::shared_ptr<Observer>> observers;
    int state;

public:
    void attach(std::shared_ptr<Observer> observer) override {
        observers.push_back(observer);
    }

    void detach(std::shared_ptr<Observer> observer) override {
        observers.remove(observer);
    }

    void notify() override {
        for (const auto& observer : observers) {
            observer->update(state);
        }
    }

    void setState(int newState) {
        state = newState;
        notify();
    }

    int getState() const {
        return state;
    }
};


// 具体观察者类  (从Observer 类派生)
class ConcreteObserver : public Observer {
private:
    std::string name;
    int observedState;

public:
    ConcreteObserver(const std::string& name) : name(name) {}

    void update(int state) override {
        observedState = state;
        std::cout << "Observer " << name << " updated with state: " << observedState << std::endl;
    }
};

int main() {
    // 创建具体主题对象
    ConcreteSubject subject;

    // 创建观察者对象
    std::shared_ptr<Observer> observer1 = std::make_shared<ConcreteObserver>("Observer 1");
    std::shared_ptr<Observer> observer2 = std::make_shared<ConcreteObserver>("Observer 2");

    // 注册观察者
    subject.attach(observer1);
    subject.attach(observer2);

    // 改变主题状态并通知观察者
    subject.setState(1);
    subject.setState(2);

    // 注销观察者
    subject.detach(observer1);
    subject.setState(3);

    return 0;
}

转自:观察者模式的程序实例C++ - mfrbuaa - 博客园

一、什么是观察者模式
     Observer模式也叫观察者模式,它的作用是当一个对象的状态发生变化时,可以自己主动通知其它关联对象,自己主动刷新对象状态。

举个样例,用户界面能够作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。


“观察”不是“直接调用”
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。不管是观察者“观察”对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

实现观察者模式的形式

实现观察者模式有非常多形式,比較直观的一种是使用一种“注冊——通知——撤销注冊”的形式。

实现观察者模式样例

       以下是C++的实现,在C++实现中,C++中没有接口的概念,可是能够用抽象类类取代Java或C#中的接口,在C++中抽象类中从派生类中抽象出来的函数(方法),必须定义成纯虚函数,这样在后面的使用中才干够通过基类的指针来訪问这些函数,面向对象的语言中有个特点,多态仅仅能訪问两者中共同拥有的部分。

//实例源自设计模式--观察者模式(C++)_nanomsg 观察者模式 c++-CSDN博客 ,主要做了点修正.

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

class Observer;//声明提前

class Subject
{
public:
    virtual void attach(Observer *o) = 0;
    virtual void change() = 0;
    virtual void setWeather(string str) = 0;
    virtual string getWeather() = 0;
};

class Observer
{
public:
    virtual string getName() = 0;
    virtual void update(Subject *s) = 0;
};

class Earth: public Subject    //被观察对象
{
private:
    string weather;
    list<Observer * > *l;      //指针

public:
    Earth()                     
    {
        l = new list<Observer *>;
    }

    void attach(Observer *o)
    {
        this->l->push_back(o);
    };

    void change()                 //变量“通知”观察者(变量执行注册的观察者的方法)
    {
        for(list<Observer *>::iterator it = l->begin(); it != l->end(); ++it)
        {
            (*it)->update(this);
        }
    };
    void setWeather(string str)
    {
        this->weather = str;
        change();
    };
    string getWeather()
    {
        return this->weather;
    };
};
class Satellite: public Observer
{
private:
    string name;
public:
    Satellite(string str)
    {
        name = str;
    }
    string getName()
    {
        return name;
    };
    void update(Subject *s)
    {
        cout << this->getName() + " " + s->getWeather();
    }
};




int main()
{
    Earth e;
    Satellite *s1 = new Satellite("风云一号");
    Satellite *s2 = new Satellite("风云二号");
    Satellite *s3 = new Satellite("风云三号");
    Satellite *s4 = new Satellite("风云四号");
    e.attach(s1);
    e.attach(s2);
    e.attach(s3);
    e.attach(s4);
    e.setWeather("fine");



    while(1) {}
    return 0;
}

观察者模式和事件监听模式的区别

转自:观察者模式和事件监听模式的区别-CSDN博客

说到事件监听模式,很容易将它和观察者模式联系在一起。
实质上这两者完成同类型的工作。依个人理解,事件监听模式更像是观察者模式的进阶。
 
用一张图来方便描述它们的区别:


观察者模式中,‘主题’会在特定逻辑下通知所有‘观察者’。
如果这个通知不包含任何信息,那么这种实现就是通常的观察者模式。


 

    class Subject
    {
    protected:
        void notify()
        {
            for (int i = 0; i < numObservers_; i++)
            {
              observers_[i]->onNotify();
            }
        }
    };

如果‘主题’通知‘观察者’的过程带有一些<其他信息>。那么‘主题’本身已经上升成为了‘事件源’,
而通知中带有的<其他信息>经过封装就成为了事件。
 

    class Subject
    {
    protected:
        void notify(const Entity& entity, Event event)
        {
            for (int i = 0; i < numObservers_; i++)
            {
              observers_[i]->onNotify(entity, event);
            }
        }
    };

事件监听模式的优势:
在很多应用场景中,通知中附带的<其他信息>是必不可少的,
事件Event则对这些<信息>进行了封装,使它本身拥有了多态的特性。
每个事件对象就可以包含不同的信息。但各个‘观察者’提供给‘主题’的接口仍然是统一的 :
onNotify(entity, event)


举个简单的例子,某游戏中的成就系统包含两种成就:
1.达成等级成就(观察者1)    2.达成战斗力成就(观察者2)
玩家(事件源)在完成升级时会创建两个对象,
升级事件(包含玩家等级字段)     战斗力提升事件(包含玩家当前战斗力字段)。
成就系统收到事件后执行统一的逻辑:
observers_[event.type]->OnAchieveEvent(entity, event);
 
总结来说 事件监听机制就是对观察者模式进行了进一步抽象,节省了代码量。
---------------------
作者:AXuanK
来源:CSDN
原文:https://blog.csdn.net/AXuan_K/article/details/78803382
版权声明:本文为博主原创文章,转载请附上博文链接!

观察者模式===》发布订阅者模式。

发散学习:发布-订阅者模式和事件监听器模式

发布-订阅者模式和事件监听器模式 - 简书

项目经验:

用户表数据改变后, 共享内存(观察者1)里的 数据要改变 ,数据库里 版本表(观察者2)的记录也要改变。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值