Behavior.Observer观察者模式:AttachDetachWhenChangedThenUpdate, AllObserversUpdated

本文介绍了一种常用的设计模式——观察者模式,详细解释了其定义、结构和应用场景。通过一个图书促销活动的例子,展示了如何使用观察者模式实现对象间的依赖关系,使一个对象的状态变化能及时通知到所有依赖于它的对象。
观察者模式(Observer Pattern)的定义

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

 

(2)观察者模式的结构和说明(拉模型)

 

  ①Subject:目标对象,通常具如的功能:一个目标可以被多个观察者观察;目标提供对观察者的注册和退订的维护;当目标的状态发生变化时,目标负责通知所有注册的、有效的观察者

  ②Observer:定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据。

  ③ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册的、有效的观察者,让观察者执行相应的处理。

  ④ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身状态以保持和目标的相应状态一致。

【编程实验】图书促销活动

//声明文件
//行为型模式——观察者模式
//场景:图书促销活动(拉模型)
/*
 观察者模式在现实的应用系统中也有好多应用,比如像当当网、京东商城一类的电子商务网站,
 如果你对某件商品比较关注,可以放到收藏架,那么当该商品降价时,系统给您发送手机短信或邮件。
 这就是观察者模式的一个典型应用,商品是被观察者,有的叫主体;关注该商品的客户就是观察者
*/
#include <iostream>
#include <string>
#include <list>

using namespace std;


class CAbsSubject; //前向声明(被观察者)

//******************************观察者接口********************************
class CAbsObserver{
public:
	virtual ~CAbsObserver();
	virtual void Update(CAbsSubject* subject) = 0;
};
//******************************目标对象(Subject)***************************
//抽象目标对象(被观察者)
class CAbsSubject{
private:
	bool bChanged;
	list<CAbsObserver*> lstObs;
public:
	void SetChanged();
	void ClrChanged();
	bool IsChanged();
	void Attach(CAbsObserver* observer);
	void Detach(CAbsObserver* observer);
	void Notify();
};

//书——被观察者
class CBook : public CAbsSubject{
private:
	string strName;
	double dPrice;
private:
	void SetPrice(double price);
public:
	CBook(string name, double price);
	void SetName(string name);
	string GetName();
	double GetPrice();
	void Change(double price);
};
//*****************************具体的观察者*****************************
//具体观察者(一般顾客,假设只留手机号码)
class CBuyer : public CAbsObserver{
private:
	string strId;
	string strTel;
public:
	CBuyer(string id, string tel);
	~CBuyer();
	void SetId(string id);
	string GetId();
	void SetTel(string tel);
	string GetTel();
	void Update(CAbsSubject* subject);
};

//具体观察者(新华书店,假设只留email)
class CBookStore : public CAbsObserver{
private:
	string strId;
	string strEmail;
public:
	CBookStore(string id, string email);
	~CBookStore();
	void SetId(string id);
	string GetId();
	void SetEmail(string email);
	string GetEmail();
	void Update(CAbsSubject* subject);
};
//实现文件
//******************************观察者接口********************************
CAbsObserver::~CAbsObserver(){}
//******************************目标对象(Subject)***************************
//抽象目标对象(被观察者)
void CAbsSubject::SetChanged(){ bChanged = true;}
void CAbsSubject::ClrChanged(){ bChanged = false;}
bool CAbsSubject::IsChanged(){ return bChanged;}
void CAbsSubject::Attach(CAbsObserver* observer){lstObs.push_back(observer);}
void CAbsSubject::Detach(CAbsObserver* observer){lstObs.remove(observer);}
void CAbsSubject::Notify(){
	for(list<CAbsObserver*>::iterator it = lstObs.begin(); it != lstObs.end(); it++){
		CAbsObserver* pObserver = (*it);
		if(pObserver != NULL)				pObserver->Update(this);
	}
}

//书——被观察者
void CBook::SetPrice(double price){dPrice = price;}
CBook::CBook(string name, double price){strName = name; dPrice = price;}
void CBook::SetName(string name){strName = name;}
string CBook::GetName(){return strName;}
double CBook::GetPrice(){return dPrice;}
void CBook::Change(double price){
	if(dPrice != price){
		SetPrice(price);//当书的价格修改时调用该方法
		//调用父类方法,改变被观察者的状态 
		SetChanged(); Notify();//通知客户该书己降价
	}
}
//*****************************具体的观察者*****************************
//具体观察者(一般顾客,假设只留手机号码)
CBuyer::CBuyer(string id, string tel){strId = id; strTel = tel;}
CBuyer::~CBuyer(){ cout << "~CBuyer" << endl;}
void CBuyer::SetId(string id){strId = id;}
string CBuyer::GetId(){return strId;}
void CBuyer::SetTel(string tel){strTel = tel;}
string CBuyer::GetTel(){return strTel;}
void CBuyer::Update(CAbsSubject* subject){
	CBook* pBook = (CBook*)subject;
	if(pBook != NULL){ //收到通知时要进行的操作
		cout << "给一般顾客(" << strId << ")发的手机短信: " << pBook->GetName() << "降价了,目前的价格为" << pBook->GetPrice() << "元" << endl;
	}
}
//具体观察者(新华书店,假设只留email)
CBookStore::CBookStore(string id, string email){strId = id; strEmail = email;}
CBookStore::~CBookStore(){cout << "~CBookStore" << endl;}
void CBookStore::SetId(string id){strId = id;}
string CBookStore::GetId(){return strId;}
void CBookStore::SetEmail(string email){strEmail = email;}
string CBookStore::GetEmail(){return strEmail;}
void CBookStore::Update(CAbsSubject* subject){
	//CBook* pBook = dynamic_cast<CBook*>(subject);
	CBook* pBook = (CBook*)subject;
	if(pBook != NULL){ //收到通知时要进行的操作
		cout << "给新华书店(" << strId << ")发的电子邮件:" << pBook->GetName() << "降价了,目前的价格为" << pBook->GetPrice() << "元" << endl;
	}
}
//测试客户端
void main()
{
	CBook oBook("《设计模式:可复用面向对象软件的基础》", 79);
	CBuyer oBuyer("001", "138********"); //一般客户
	CBookStore oBookStore("002", "E-mail:web@hnxhbook.com.cn");//新华书店
	//增加观察者,在实际应用中就是哪些人对该书做了关注
	oBook.Attach(&oBuyer);//一般客户对该对做了关注
	oBook.Attach(&oBookStore);//新华书店对该书做了关注
	oBook.Change(60); //发送降价通知
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值