C++开发之观察者模式的实现
前言:主要是介绍了C++观察者的实现。
1.观察者模式
观察者模式是行为设计模式之一。当您对对象的状态感兴趣并希望在有任何更改时收到通知时,观察者设计模式非常有用。在观察者模式中,监视另一个对象状态的对象称为Observer,正在被监视的对象称为Subject。
2.观察者模式简单实现
#include <iostream>
#include <windows.h>
using namespace std;
//观察者
class Observer;
//被观察者
class Subject{
Observer *ob;
public:
//1. 目标对象要知道被谁观察, 因为一会目标对象的状态发生了改变,能够通知观察者.
void addObserver(Observer *ob){
this->ob = ob;
}
//2. 如果这个目标对象的状态发生了改变,那么它需要通知观察者.
void notify();
};
//观察者
class Observer{
Subject *sj;//也必须持有目标对象的实例。
public:
void addSubject(Subject *sj){//注册观察的目标对象
this->sj = sj;
}
//要接收目标对象的通知。
void update(){
cout << "收到了来自目标对象的通知。"<<endl;
}
};
void Subject::notify() {
ob->update();
}
int main() {
Subject sj;
Observer ob;
sj.addObserver(&ob);
ob.addSubject(&sj);
for(int i = 1 ; i < 100 ; i++){
cout << "i ===>" << i << endl;
if(i % 10 == 0 ){
//使用i 整除10 ,来模拟目标对象的状态发生了改变。 进而让观察者收到通知
sj.notify();
}
Sleep(1000);
}
return 0;
}
3.观察者模式进阶
增加了多个观察者,并且在某些观察者对象销毁的时候,从目标对象(被观察者)里面移除该对象。
#include <iostream>
#include <thread>
#include <zconf.h>
#include <list>
using namespace std;
class Observer;
class subject{
//被谁观察, 以及通知的函数。
list<Observer *> ob_list;
public:
//添加被谁观察。
void addObserver(Observer * ob){
ob_list.push_back(ob);
}
//通知所有的观察者。
void notify();
//从被谁观察的集合中移除某个观察者
void removeObserver(Observer * ob){
ob_list.remove(ob);
}
};
class Observer{
subject *sj;
//得知道观察谁
string name;
public:
Observer(string name ): name(name){}
//知道要观察谁。
void addSubject(subject *sj){
this->sj = sj;
}
void update(){
cout << name <<" :: 观察者收到通知了。" <<endl;
}
~Observer(){
//对象已经挂掉了之后,就要让被观察者移除对象。
sj->removeObserver(this);
}
};
void subject::notify() {
for(Observer * ob : ob_list){
ob->update();
}
}
int main() {
subject sj;
Observer ob1("观察者1号"); //观察者1
Observer *ob2 = new Observer("观察者2号");//观察者2
sj.addObserver(&ob1);
sj.addObserver(ob2);
ob1.addSubject(&sj);
ob2->addSubject(&sj);
for (int i = 1; i < 100; ++i) {
cout << "i-===" << i << endl;
if(i % 5 == 0 ){
sj.notify();
}
if(i == 17){
delete ob2;
}
usleep(1000 * 500);
}
return 0;
}
4.观察者模式强化
一般来说,观察者模式并不是只有两个类: subject 和 observer 。 由于观察者模式的通用性,以及面向对象的流行,通常会把他们两个做成抽象类,然后在配合各自的子类来实现观察者模式。
#include <iostream>
#include <thread>
#include <future>
#include <zconf.h>
#include <list>
using namespace std;
class Observer;
//抽象类
class Subject{
public:
//添加观察者 , 移除观察者 , 通知观察者
virtual void addObserver(Observer*) =0;
virtual void removeObserver(Observer*)=0;
virtual void notify(string)=0;
};
//抽象类
class Observer{
public:
//添加被观察者, 接收通知, 析构函数: 取消注册
virtual void addSubject(Subject*) = 0;
virtual void update(string) = 0; //收到的是什么通知
virtual ~Observer()= default; //要做成虚函数吗?
};
//真正的被观察者实现: 班长
class ClassMonitor : public Subject{
list<Observer*> ob_list;
void addObserver(Observer * ob){
ob_list.push_back(ob);
}
void removeObserver(Observer* ob){
ob_list.remove(ob);
}
void notify(string message){
for(Observer * ob : ob_list){
ob->update(message);
}
}
};
//真正的观察者实现
class GameStudent : public Observer{
public:
Subject* sj;
void addSubject(Subject* sj){
this->sj = sj;
}
void update(string message){
cout << message << " 赶紧关闭游戏。" << endl;
}
~GameStudent(){
cout << "执行游戏的析构" <<endl;
sj->removeObserver(this);
}
};
class NBAStudent : public Observer{
public:
Subject* sj;
void addSubject(Subject* sj){
this->sj = sj;
}
void update(string message){
cout << message << " 不要看NBA。" << endl;
}
~NBAStudent(){
cout << "执行NBA的析构" <<endl;
sj->removeObserver(this);
}
};
class ChatStudent : public Observer{
public:
Subject* sj;
void addSubject(Subject* sj){
this->sj = sj;
}
void update(string message){
cout << message << " 不要聊天。" << endl;
}
~ChatStudent(){
cout << "执行聊天的析构" <<endl;
sj->removeObserver(this);
}
};
int main() {
Subject * sj = new ClassMonitor();
Observer * game = new GameStudent();
Observer * nba = new NBAStudent();
Observer * chat = new ChatStudent();
//有哪些观察者观察这个目标
sj->addObserver(game);
sj->addObserver(nba);
sj->addObserver(chat);
game->addSubject(sj);
nba->addSubject(sj);
chat->addSubject(sj);
for (int i = 1; i < 100; ++i) {
cout << "i ===>" << i << endl;
if(i % 20 == 0){
sj->notify("出大事了,班长感冒了");
}else if(i % 10 == 0){
sj->notify("小心,校长来了");
}else if(i % 5 == 0){
sj->notify("小心,丽姐来了");
}
if(i == 7){
delete game; //执行父类的析构函数
}
usleep(1000 * 600);
}
return 0;
}
结束!!!