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