观察者(Observer)模式

背景
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”,一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过去亲密,将使软件不能很好的抵御变化。
特点
观察者模式定义对象间的一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖它的对象都得到通知并且自动更新。
使用面向对象的抽象,观察者模式使得我们可以独立地改变目标与观察者,从而使得二者之间的依赖关系达到松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
观察者自己决定是否需要订阅通知,目标对象对此一无所知。
观察者模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的额一个重要组成部分。
C++代码实现

//Subject.h
#pragma once
#include<list>
#include<string>
using namespace std;
class Observer;
class Subject {
public:
	virtual ~Subject();
	virtual void detach(Observer* obs);
	virtual void attach(Observer* obs);
	virtual void notify();
	virtual void setState(const string& str) = 0;
	virtual string getState() = 0;
protected:
	Subject();
private:
	list<Observer*>* obs;
};
class ConcreteSubject :public Subject {
public:
	~ConcreteSubject();
	ConcreteSubject();
	void setState(const string& str);
	string getState();
private:
	string state;
};
//Subject.cpp
#include"Observer.h"
#include"Subject.h"
#include<iostream>
#include<list>
using namespace std;
Subject::Subject() {
	obs = new list<Observer*>;
}
Subject::~Subject() {

}
void Subject::attach(Observer* obs) {
	this->obs->push_front(obs);
}
void Subject::detach(Observer* obs) {
	this->obs->remove(obs);
}
void Subject::notify() {
	list<Observer*> ::iterator it = obs->begin();
	for (; it != obs->end(); it++) {
		(*it)->update(this);
	}
}
ConcreteSubject::ConcreteSubject() {
	state = '\0';
}
ConcreteSubject::~ConcreteSubject() {

}
void ConcreteSubject::setState(const string& str) {
	state = str;
}
string ConcreteSubject::getState() {
	return state;
}
//Observer.h
#pragma once
class Subject;
#include<string>
using namespace std;
class Observer {
public:
	virtual ~Observer();
	virtual void update(Subject* sub) = 0;
	virtual void printinfo() = 0;
protected:
	string state;
	Observer();
};
class ConcreteObserverA :public Observer {
public:
	~ConcreteObserverA();
	ConcreteObserverA(Subject* sub);
	virtual Subject* getSubject();
	void update(Subject* sub);
	void printinfo();
private:
	Subject* sub;
};
class ConcreteObserverB :public Observer {
public:
	~ConcreteObserverB();
	ConcreteObserverB(Subject* sub);
	virtual Subject* getSubject();
	void update(Subject* sub);
	void printinfo();
private:
	Subject* sub;
};
//Observer.cpp
#include"Observer.h"
#include"Subject.h"
#include<list>
#include<string>
#include<iostream>
using namespace std;
Observer::Observer() {
	state = '\0';
}
Observer::~Observer() {

}
ConcreteObserverA::ConcreteObserverA(Subject* sub) {
	this->sub = sub;
	this->sub->attach(this);
}
ConcreteObserverA::~ConcreteObserverA() {
	this->sub->detach(this);
	if (sub) {
		delete sub;
	}
}
Subject* ConcreteObserverA::getSubject() {
	return sub;
}
void ConcreteObserverA::printinfo() {
	cout << "ConcreteObserverA:" << sub->getState() << endl;
}
void ConcreteObserverA::update(Subject* sub) {
	state = sub->getState();
	printinfo();
}
ConcreteObserverB::ConcreteObserverB(Subject* sub) {
	this->sub = sub;
	this->sub->attach(this);
}
ConcreteObserverB::~ConcreteObserverB() {
	this->sub->detach(this);
	if (sub) {
		delete sub;
	}
}
void ConcreteObserverB::printinfo() {
	cout << "ConcreteObserverB:" << sub->getState() << endl;
}
void ConcreteObserverB::update(Subject* sub) {
	state = sub->getState();
	printinfo();
}
Subject* ConcreteObserverB::getSubject() {
	return sub;
}
//Main.cpp
#include"Observer.h"
#include"Subject.h"
#include<iostream>
using namespace std;
int main() {
	Subject* sub = new ConcreteSubject();
	Observer* obsa = new ConcreteObserverA(sub);
	Observer* obsb = new ConcreteObserverB(sub);
	sub->setState("old");
	sub->notify();
	sub->setState("new");
	sub->notify();
	return 0;
}

代码说明
在观察模式当中,Subject维护一个list容器作为存储所有观察者的容器。每次调用notify()都会遍历容器中Observer对象,并且调用Observer的update操作用来通知改变状态。目标状态state可以由于Subject改变也可以由于Observer里面调用Subject的SetState操作改变。
运行程序会发现当Subject处于old的时候,两个观察者都是old,当Subject处于new的时候,两个观察者都是new。
运行结果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值