观察者【设计模式】

本文介绍了观察者设计模式,它定义了一种一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。在C++中,观察者模式的实现通常涉及到虚析构函数的使用,以防止内存泄漏。同时,文章通过示例解释了为什么基类需要使用虚析构函数。
摘要由CSDN通过智能技术生成

知识点

观察者

知识要点

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。观察者模式的特点是主体类的基类处理与观察者的操作,绑定观察者,解绑定观察者,通知观察者等,主体类的实现类在需要通知的方法中调用基类的通知方法即可,不需要关心通知的细节(细节被封装在主体的基类中)。而在观察者的实现类中,需要设计一个指向主体的指针,这个指针的作用是为具体的观察者对象绑定被观察的主体。观察者类中有一个通用的状态更新的方法,主体的基类来调用这个方法实现观察者类中状态的更新。

 

观察者模式是很常见的模式。MVC中的M是这里的主体类,V是这里的观察者类。

参考https://www.cnblogs.com/carsonzhu/p/5770253.html

示例

为什么基类要用虚析构函数?

C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。

#include<iostream>
#include<list>

using namespace std;

class Observer  // 观察者基类
{
  public:
    virtual void update() = 0;  // 只包含对观察者中被观察对象的状态的更新操作
};

class Subject  // 主体基类,被观察的对象,包含对观察者类的绑定,解绑定,通知操作
{
  private:
    list<Observer*> Observers;  //拥有所有观察者的指针列表
  protected:
    Subject(){};  //默认构造函数
  public:
    virtual ~Subject(){};  //默认析构函数,必须有
    virtual void Attach(Observer* observer)  //绑定一个观察者类
    {
      Observers.push_back(observer);
    }

    virtual void Detach(Observer* observer)  //解绑定一个观察者类
    {
      Observers.remove(observer);
    }
    virtual void notify()  // 通知所有的观察者更新状态值。
    {
      for( list<Observer*>::iterator it = Observers.begin(); it != Observers.end(); it ++)
        (*it) -> update();
    }
};


class ConcreteSubject:public Subject  // 具体主体类,继承主体基类
{
  private:
    int subjectState;  //具体主题类的状态
  public:
    ConcreteSubject(int mySubState):subjectState(mySubState) {}  //构造函数
    int GetState()  //查看状态
    {
      return this -> subjectState;
    }
    void SetState(int newState) //设置状态
    {
       this -> subjectState = newState; 
       Subject::notify();  //调用基线通知方法通知所有观察者,屏蔽了所有观察者操作。
    }
};

class ConcreteObserver:public Observer // 具体观察者类,继承观察者基类
{
  private:
    int observerState;  //观察者当前状态
    ConcreteSubject* concreteSubject; //被观察对象
  public:
    ConcreteObserver(ConcreteSubject* mySubject)  //构造函数,每个观察者必须有一个被观察的主体
    {
      concreteSubject = mySubject;
      concreteSubject -> Attach(this); //构造时,为被观察的主题绑定自己。重点圈圈
    }
    ~ConcreteObserver()  //析构函数,解绑定自己。
    {
      concreteSubject -> Detach(this);//析构时,为被观察的主题解绑定自己
    }
    virtual void update()  // 观察者更新自己,一般通过具体主体类的notify方法类调用,将主体类的状态更新到观察者自己身上来
    {
      observerState = concreteSubject -> GetState();
      cout << "ConcreteObserver's state is " << observerState << endl;
      cout << "updated!" << endl; 
    }
};

int main()
{
  ConcreteSubject* concreteSubject = new ConcreteSubject(0); //生成一个具体主题类
  Observer* myObserver = new ConcreteObserver(concreteSubject);//用具体主体类初始化一个具体观察者。
  concreteSubject -> SetState(5); //对具体主体设置状态,将自动通知到观察者类。
  return 0;
}

链接

https://github.com/xierensong/learngit/blob/master/DPattern/3/1.cpp

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值