C++ 设计模式-观察者模式

设计模式介绍

一、观察者模式

1. 观察者模式定义

定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

2. 观察者模式本质

观察者模式的本质:触发联动

3. 观察者模式结构和说明

(1) 结构

在这里插入图片描述
在这里插入图片描述

(2) 调用顺序

在这里插入图片描述
在这里插入图片描述

4. 观察者模式适用情况

  • 当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化,那么就可以选用观察者模式,将这两者封装成观察者和目标对象,当目标对象变化的时候,依赖于它的观察者对象也会发生相应的变化。这样就把抽象模型的这两个方面分离开了,使得它们可以独立地改变和复用。
  • 如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变,这种情况可以选用观察者模式,被更改的那一个对象很明显就相当于是目标对象,而需要连带修改的多个其他对象,就作为多个观察者对象了。
  • 当一个对象必须通知其他的对象,但是你又希望这个对象和其他被它通知的对象是松散耦合的。也就是说这个对象其实不想知道具体被通知的对象。这种情况可以选用观察者模式,这个对象就相当于是目标对象,而被它通知的对象就是观察者对象了。

5. 观察者模式优缺点

(1) 优点
  • 观察者模式实现了观察者和目标之间的抽象耦合
    原本目标对象在状态发生改变的时候,需要直接调用所有的观察者对象,但是抽象出观察者接口以后,目标和观察者就只是在抽象层面上耦合了,也就是说目标只是知道观察者接口,并不知道具体的观察者的类,从而实现目标类和具体的观察者类之间解耦。
  • 观察者模式实现了动态联动
    所谓联动,就是做一个操作会引起其他相关的操作。由于观察者模式对观察者注册实行管理,那就可以在运行期间,通过动态地控制注册的观察者,来控制某个动作的联动范围,从而实现动态联动。
  • 观察者模式支持广播通信
    由于目标发送通知给观察者是面向所有注册的观察者,所以每次目标通知的信息就要对所有注册的观察者进行广播。当然,也可以通过在目标上添加新的功能来限制广播的范围。
    在广播通信的时候要注意一个问题,就是相互广播造成死循环的问题。比如A和B两个对象互为观察者和目标对象,A对象发生状态变化,然后A来广播信息,B对象接收到通知后,在处理过程中,使得B对象的状态也发生了改变,然后B来广播信息,然后A对象接到通知后,又触发广播信息…,如此A引起B变化,B又引起A变化,从而一直相互广播信息,就造成死循环。
(2) 缺点
  • 可能会引起无谓的操作
    由于观察者模式每次都是广播通信,不管观察者需不需要,每个观察者都会被调用update方法,如果观察者不需要执行相应处理,那么这次操作就浪费了。其实浪费了还好,最怕引起误更新,那就麻烦了,比如,本应该在执行这次状态更新前把某个观察者删除掉,这样通知的时候就没有这个观察者了,但是现在忘掉了,那么就会引起误操作。

6. 相关模式

  • 观察者模式和状态模式
    观察者模式和状态模式是有相似之处的。
    观察者模式是当目标状态发生改变时,触发并通知观察者,让观察者去执行相应的操作。而状态模式是根据不同的状态,选择不同的实现,这个实现类的主要功能就是针对状态相应地操作,它不像观察者,观察者本身还有很多其他的功能,接收通知并执行相应处理只是观察者的部分功能。
    当然观察者模式和状态模式是可以结合使用的。观察者模式的重心在触发联动,但是到底决定哪些观察者会被联动,这时就可以采用状态模式来实现了,也可以采用策略模式来进行选择需要联动的观察者。
  • 观察者模式和中介者模式
    观察者模式和中介者模式是可以结合使用的。前面的例子中目标都只是简单地通知一下,然后让各个观察者自己去完成更新就结束了。如果观察者和被观察的目标之间的交互关系很复杂,比如,有一个
    界面,里面有三个下拉列表组件,分别是选择国家、省份州、具体的城市,很明显这是一个三级联动,当你选择一个国家的时候,省份/州应该相应改变数据,省份/州一改变,具体的城市也需要改变。这种情况下,很明显需要相关的状态都联动准备好了,然后再一次性地通知观察者。也就是界面做更新处理,不会仅国家改变一下,省份和城市还没有改,就通知界面更新。这种情况就可以使用中介者模式来封装观察者和目标的关系

二、观察者模式示例代码

#include <iostream>
#include <string>
#include <list>

using namespace std;

//观察者模式拉模型实现

class BlogBase;

//观察者
class ObserverBase
{
public:
    ObserverBase() = default;
    virtual ~ObserverBase() = default;
    virtual void Update(const BlogBase& blog) = 0;
};

//博客
class BlogBase
{
public:
    BlogBase() = default;
    virtual ~BlogBase()  = default;
    void Attach(ObserverBase *observer) { m_observers.push_back(observer); }	 //添加观察者
    void Remove(ObserverBase *observer) { m_observers.remove(observer); }        //移除观察者
    void Notify(const BlogBase& blog) //通知观察者
    {
        auto iter = m_observers.begin();
        for(; iter != m_observers.end(); iter++)
            (*iter)->Update(blog);
    }

    virtual void SetStatus(string s) = 0; //设置状态
    virtual string GetStatus() const= 0;    //获得状态
private:
    list<ObserverBase* > m_observers; //观察者链表
};

//具体博客类
class BlogCSDN : public BlogBase
{
private:
    string m_name; //博主名称
public:
    explicit BlogCSDN(string name): m_name(std::move(name)) {}
    ~BlogCSDN() override  = default;

    void SetStatus(string s) override {  //具体设置状态信息
        m_status = "CSDN:" + m_name + ":" + s;
        Notify(*this);
    }
    string GetStatus() const override { return m_status; }

protected:
    string m_status; //状态
};

//具体观察者
class ObserverBlogCSDN : public ObserverBase
{
private:
    string m_name;  //观察者名称
public:
    ObserverBlogCSDN(string name): m_name(std::move(name)){}
    ~ObserverBlogCSDN() override  = default;
    void Update(const BlogBase& blog) override
    {
        cout<<m_name<<" observer->"<<blog.GetStatus()<<endl;  //拉模型
    }
};

int main(){
    BlogBase *blog = new BlogCSDN("wangdaming");
    ObserverBase *observer1 = new ObserverBlogCSDN("wangdaming");
    blog->Attach(observer1);
    blog->SetStatus("DesignMode");
    blog->SetStatus("DataStruct");
    blog->Remove(observer1);
    delete blog;
    delete observer1;
    return 0;
}
#include <iostream>
#include <string>
#include <list>

using namespace std;

//观察者模式推模型实现

class BlogBase;

//观察者
class ObserverBase
{
public:
    ObserverBase() = default;
    virtual ~ObserverBase() = default;
    virtual void Update(const std::string& status) = 0;
};

//博客
class BlogBase
{
public:
    BlogBase() = default;
    virtual ~BlogBase()  = default;
    void Attach(ObserverBase *observer) { m_observers.push_back(observer); }	 //添加观察者
    void Remove(ObserverBase *observer) { m_observers.remove(observer); }        //移除观察者
    void Notify(const std::string& status) //通知观察者
    {
        auto iter = m_observers.begin();
        for(; iter != m_observers.end(); iter++)
            (*iter)->Update(status);
    }

    virtual void SetStatus(string s) = 0; //设置状态
    virtual string GetStatus() const= 0;    //获得状态
private:
    list<ObserverBase* > m_observers; //观察者链表
};

//具体博客类
class BlogCSDN : public BlogBase
{
private:
    string m_name; //博主名称
public:
    explicit BlogCSDN(string name): m_name(std::move(name)) {}
    ~BlogCSDN() override  = default;

    void SetStatus(string s) override {  //具体设置状态信息
        m_status = "CSDN:" + m_name + ":" + s;
        Notify(m_status);
    }
    string GetStatus() const override { return m_status; }

protected:
    string m_status; //状态
};

//具体观察者
class ObserverBlogCSDN : public ObserverBase
{
private:
    string m_name;  //观察者名称
public:
    ObserverBlogCSDN(string name): m_name(std::move(name)){}
    ~ObserverBlogCSDN() override  = default;
    void Update(const std::string& status) override
    {
        cout<<m_name<<" observer->"<<status<<endl;  //推模型
    }
};

int main(){
    BlogBase *blog = new BlogCSDN("wangdaming");
    ObserverBase *observer1 = new ObserverBlogCSDN("wangdaming");
    blog->Attach(observer1);
    blog->SetStatus("DesignMode");
    blog->SetStatus("DataStruct");
    blog->Remove(observer1);
    delete blog;
    delete observer1;
    return 0;
}
#include <iostream>
#include <string>
#include <list>

using namespace std;

//动态触发联动:区别对待观察者

class BlogBase;

//观察者
class ObserverBase
{
public:
    ObserverBase() = default;
    virtual ~ObserverBase() = default;
    virtual void Update(const BlogBase& blog) = 0;
    virtual std::string GetName() = 0;
};

//博客
class BlogBase
{
public:
    BlogBase() = default;
    virtual ~BlogBase()  = default;
    void Attach(ObserverBase *observer) { m_observers.push_back(observer); }	 //添加观察者
    void Remove(ObserverBase *observer) { m_observers.remove(observer); }        //移除观察者

    virtual void SetStatus(string s) = 0; //设置状态
    virtual string GetStatus() const= 0;    //获得状态

    virtual void SetOp(string op) = 0; //设置操作
    virtual string GetOp() const= 0;    //获得操作

protected:
    virtual void Notify(const BlogBase& blog) //通知观察者
    {
        auto iter = m_observers.begin();
        for(; iter != m_observers.end(); iter++)
        {
            (*iter)->Update(blog);
        }
    }

protected:
    list<ObserverBase* > m_observers; //观察者链表
};

//具体博客类
class BlogCSDN : public BlogBase
{
private:
    string m_name; //博主名称
public:
    explicit BlogCSDN(string name): m_name(std::move(name)) {}
    ~BlogCSDN() override  = default;

    void SetStatus(string s) override {  //具体设置状态信息
        m_status = "CSDN:" + m_name + ":" + s;
        Notify(*this);
    }
    string GetStatus() const override { return m_status; }

    void SetOp(string op) override {  //具体设置状态信息
        m_op = op;
    }
    string GetOp() const override { return m_op; }

protected:
    void Notify(const BlogBase& blog) override //通知观察者
    {
        auto iter = m_observers.begin();
        for(; iter != m_observers.end(); iter++)
        {
            std::string op = GetOp();
            if(op == "modify" && (*iter)->GetName() == "wangdaming")
            {
                (*iter)->Update(blog);
            }

            if(op == "update" && (*iter)->GetName() == "others")
            {
                (*iter)->Update(blog);
            }
        }
    }
protected:
    string m_status ; //状态
    string m_op ;//操作
};

//具体观察者
class ObserverBlogCSDN : public ObserverBase
{
public:
    ObserverBlogCSDN(string name): m_name(std::move(name)){}
    ~ObserverBlogCSDN() override  = default;
    void Update(const BlogBase& blog) override
    {
        cout<<m_name<<" observer->"<<blog.GetStatus()<<":"<<blog.GetOp()<<endl;  //拉模型
    }
    std::string GetName() override
    {
        return m_name;
    }

private:
    string m_name;  //观察者名称
};

int main(){
    BlogBase *blog = new BlogCSDN("wangdaming");
    ObserverBase *observer1 = new ObserverBlogCSDN("wangdaming");
    ObserverBase *observer2 = new ObserverBlogCSDN("others");
    blog->Attach(observer1);
    blog->Attach(observer2);

    blog->SetOp("modify");
    blog->SetStatus("DesignMode");

    blog->SetOp("update");
    blog->SetStatus("DataStruct");

    blog->Remove(observer1);
    blog->Remove(observer2);
    delete blog;
    delete observer1;
    return 0;
}

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

using namespace std;

//观察者模式拉模型实现
//采用weak_ptr方式实现观察者列表
//优点:观察者目标类能知道观察者列表中的对象是否有效

class BlogBase;

//观察者
class ObserverBase
{
public:
    ObserverBase() = default;
    virtual ~ObserverBase() = default;
    virtual void Update(const BlogBase& blog) = 0;
};

//博客
class BlogBase
{
public:
    BlogBase() = default;
    virtual ~BlogBase()  = default;
    void Attach(std::weak_ptr<ObserverBase>&& observer)  //添加观察者
    {
        m_observers.push_back(std::move(observer));
    }
    void Remove(const std::weak_ptr<ObserverBase>& observer) //移除观察者
    {
        m_observers.remove_if([&](const std::weak_ptr<ObserverBase>& item)->bool{
            if(!item.expired())
            {
                return item.lock() == observer.lock();
            }
            return false;
        });
    }
    void Notify(const BlogBase& blog) //通知观察者
    {
        auto iter = m_observers.begin();
        for(; iter != m_observers.end();)
        {
            if(!iter->expired())
            {
                iter->lock()->Update(blog);
                iter++;
            } else{
                std::cout<<"observer is null."<<std::endl;
                iter = m_observers.erase(iter);
            }
        }
    }

    uint32_t Size(){return m_observers.size();}

    virtual void SetStatus(string s) = 0; //设置状态
    virtual string GetStatus() const= 0;    //获得状态
private:
    list<std::weak_ptr<ObserverBase>> m_observers; //观察者链表
};

//具体博客类
class BlogCSDN : public BlogBase
{
private:
    string m_name; //博主名称
public:
    explicit BlogCSDN(string name): m_name(std::move(name)) {}
    ~BlogCSDN() override  = default;

    void SetStatus(string s) override {  //具体设置状态信息
        m_status = "CSDN:" + m_name + ":" + s;
        Notify(*this);
    }
    string GetStatus() const override { return m_status; }

protected:
    string m_status; //状态
};

//具体观察者
class ObserverBlogCSDN : public ObserverBase
{
private:
    string m_name;  //观察者名称
public:
    ObserverBlogCSDN(string name): m_name(std::move(name)){}
    ~ObserverBlogCSDN() override  = default;
    void Update(const BlogBase& blog) override
    {
        cout<<m_name<<" observer->"<<blog.GetStatus()<<endl;  //拉模型
    }
};

int main(){
    BlogBase *blog = new BlogCSDN("wangdaming");
    std::shared_ptr<ObserverBase> pShare1 = std::make_shared<ObserverBlogCSDN>("wangdaming");
    blog->Attach(pShare1);
    {
        std::shared_ptr<ObserverBase> pShare2 = std::make_shared<ObserverBlogCSDN>("others");
        blog->Attach(pShare2);
        blog->SetStatus("DesignMode");
    }
    blog->SetStatus("DataStruct");
    blog->Remove(pShare1);
    delete blog;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言实现观察者模式需要以下步骤: 1. 定义一个观察者接口(Observer),包含一个更新方法(update),用于接收被观察者(Subject)的通知。 2. 定义一个被观察者接口(Subject),包含添加观察者、删除观察者、通知观察者等方法。 3. 实现观察者接口,创建具体的观察者类。 4. 实现被观察者接口,创建具体的被观察者类,并在其中维护一个观察者列表。 5. 当被观察者发生变化时,调用通知方法,将变化传递给所有观察者。 以下是C语言实现观察者模式的示例代码: ``` #include <stdio.h> #include <stdlib.h> typedef struct Observer Observer; typedef struct Subject Subject; // 观察者接口 struct Observer { void (*update)(Observer *); }; // 被观察者接口 struct Subject { void (*attach)(Subject *, Observer *); void (*detach)(Subject *, Observer *); void (*notify)(Subject *); }; // 具体观察者 struct ConcreteObserver { Observer base; int state; }; void ConcreteObserver_update(Observer *observer) { ConcreteObserver *self = (ConcreteObserver *)observer; printf("Observer state update: %d\n", self->state); } ConcreteObserver *ConcreteObserver_create(int state) { ConcreteObserver *self = malloc(sizeof(ConcreteObserver)); self->base.update = ConcreteObserver_update; self->state = state; return self; } // 具体被观察者 struct ConcreteSubject { Subject base; Observer **observers; int count; }; void ConcreteSubject_attach(Subject *subject, Observer *observer) { ConcreteSubject *self = (ConcreteSubject *)subject; self->count++; self->observers = realloc(self->observers, sizeof(Observer *) * self->count); self->observers[self->count - 1] = observer; } void ConcreteSubject_detach(Subject *subject, Observer *observer) { ConcreteSubject *self = (ConcreteSubject *)subject; for (int i = 0; i < self->count; i++) { if (self->observers[i] == observer) { for (int j = i; j < self->count - 1; j++) { self->observers[j] = self->observers[j + 1]; } self->count--; self->observers = realloc(self->observers, sizeof(Observer *) * self->count); break; } } } void ConcreteSubject_notify(Subject *subject) { ConcreteSubject *self = (ConcreteSubject *)subject; for (int i = 0; i < self->count; i++) { self->observers[i]->update(self->observers[i]); } } ConcreteSubject *ConcreteSubject_create() { ConcreteSubject *self = malloc(sizeof(ConcreteSubject)); self->base.attach = ConcreteSubject_attach; self->base.detach = ConcreteSubject_detach; self->base.notify = ConcreteSubject_notify; self->observers = NULL; self->count = 0; return self; } int main() { ConcreteSubject *subject = ConcreteSubject_create(); ConcreteObserver *observer1 = ConcreteObserver_create(1); ConcreteObserver *observer2 = ConcreteObserver_create(2); subject->base.attach(&subject->base, &observer1->base); subject->base.attach(&subject->base, &observer2->base); subject->base.notify(&subject->base); subject->base.detach(&subject->base, &observer2->base); subject->base.notify(&subject->base); free(observer1); free(observer2); free(subject->observers); free(subject); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值