第十四章 老板回来我不知道--观察者模式(读书笔记)

首先我们来看看下面的代码:

/*同事的类,在这里他要知道秘书的存在才可以*/
#pragma once
#include <string>

class Secretary;
class StockObserver
{
public:
	StockObserver(void);
	StockObserver(std::string name, Secretary* sub);
	~StockObserver(void);

	void Update(void);
private:
	//观察者的名字
	std::string m_name;
	//通知者(秘书)的指针
	Secretary* m_pSecretary;
};
#include "StockObserver.h"
#include <iostream>
#include "Secretary.h"

StockObserver::StockObserver(void)
{
}

StockObserver::~StockObserver(void)
{
}
//观察者的名字和通知者的指针
StockObserver::StockObserver(std::string name, Secretary* sub)
{
	this->m_name = name;
	this->m_pSecretary = sub;
}

void StockObserver::Update(void)
{
	std::string str = m_pSecretary->GetSecretaryAction();
	std::cout << m_name 
		<< str <<"please close it"
		<< std::endl;
}

当老板回来的时候,秘书要这样通知他们的同伴

/*Secretary.h*/
#pragma once
#include <list>
#include <string>

class StockObserver;
class Secretary
{
public:
	Secretary(void);
	~Secretary(void);
public:
	//加入观察者
	void Attach(StockObserver* pObs);
	//通知
	void Notify(void);
	//得到秘书的动作
	void SetSecretaryAction(std::string);
	//实施秘书的动作
	std::string GetSecretaryAction(void);
private:
	//观察者们
	std::list<StockObserver*> m_Observer;
	//联络观察者的动作
	std::string m_action;
};
/*Secretary.cpp*/
#include "Secretary.h"
#include "StockObserver.h"

Secretary::Secretary(void)
{
}

Secretary::~Secretary(void)
{
}

//加入观察者
void Secretary::Attach(StockObserver* pObs)
{
	m_Observer.push_back(pObs);
}
//秘书联络观察者
void Secretary::Notify(void)
{
	std::list<StockObserver*>::const_iterator iter = m_Observer.begin();
	for (; iter != m_Observer.end(); ++iter)
	{
		(*iter)->Update();
	}
}
//设置秘书的动作
void Secretary::SetSecretaryAction(std::string action)
{
	m_action = action;
}
//得到秘书的工作
std::string Secretary::GetSecretaryAction(void)
{
	return m_action;
}

最后是调用上面两个类的Main函数:

#include "Secretary.h"
#include "StockObserver.h"

int main(int argc, char* argv[])
{
	//通知者
	Secretary* tongzhizhe = new Secretary();
	//观察者生成,但要先认识下通知者
	StockObserver* workmate1 = new StockObserver("A ", tongzhizhe);
	StockObserver* workmate2 = new StockObserver("B ", tongzhizhe);
	//先让通知者知道观察者
	tongzhizhe->Attach(workmate1);
	tongzhizhe->Attach(workmate2);
	//通知的方式设定
	tongzhizhe->SetSecretaryAction("Boss is coming back");
	//开始通知
	tongzhizhe->Notify();

	delete tongzhizhe;
	delete workmate1;
	delete workmate2;
	return 0;
}

大家看了这个程序,应该都发觉了,通知者和观察者的耦合问题。现在都已经相互包含了。

1.(14.2)这个“前台”类和这个“看股票者”类之间相互耦合了,前台类要增加观察者,观察者类也需要前台的状态。
2.(14.3 解耦实践一)在这里,把所有的与具体观察者耦合的地方都改成了“抽象观察者”,针对了抽象编程,所以减少了与具体类的耦合。但是在这里没有把前台秘书这个具体类给抽象出来。

首先是通知者类:

#pragma once
#include <list>
#include <string>
/*秘书通知者类,基本同上*/
class Observer;
class Secretary
{
public:
	Secretary(void);
	~Secretary(void);
public:
	void Attach(Observer* pObs);
	void Detach(Observer* pObs);
	void Notify(void);
	void SetSecretaryAction(std::string);
	std::string GetSecretaryAction(void);
private:
	std::list<Observer*> m_Observer;
	std::string m_action;
};
#include "Secretary.h"
#include "Observer.h"

Secretary::Secretary(void)
{
}

Secretary::~Secretary(void)
{
}
void Secretary::Attach(Observer* pObs)
{
	m_Observer.push_back(pObs);
}
void Secretary::Detach(Observer* pObs)
{
	m_Observer.remove(pObs);
}
void Secretary::Notify(void)
{
	std::list<Observer*>::const_iterator iter = m_Observer.begin();
	for (; iter != m_Observer.end(); ++iter)
	{
		(*iter)->Update();
	}
}
void Secretary::SetSecretaryAction(std::string action)
{
	m_action = action;
}
std::string Secretary::GetSecretaryAction(void)
{
	return m_action;
}


抽象的观察者:

#pragma once
#include <string>
/*有抽象在这个观察者里面了*/
class Secretary;
class Observer
{
public:
	Observer(std::string name, Secretary* sub)
	{
		this->m_name = name;
		this->m_pSecretary = sub;
	};
	virtual ~Observer(void){};

	virtual void Update(void){};
protected:
	std::string m_name;
	Secretary* m_pSecretary;
	Observer(void){};
};


具体的观察者:

#pragma once
#include "observer.h"

class NBAObserver : public Observer
{
public:
	NBAObserver(std::string name, Secretary* sub);
	~NBAObserver(void);

	void Update(void);
private:
	NBAObserver(void);
};

 

#include "NBAObserver.h"
#include <iostream>
#include "secretary.h"

NBAObserver::NBAObserver(void)
{
}

NBAObserver::~NBAObserver(void)
{
}

NBAObserver::NBAObserver(std::string name, Secretary* sub)
:Observer(name, sub)
{
}

void NBAObserver::Update(void)
{
	std::string str = m_pSecretary->GetSecretaryAction();
	std::cout << m_name 
		<< str <<"please stop Watching NBA"
		<< std::endl;
}

 

#pragma once
#include "observer.h"

class StockObserver : public Observer
{
public:
	StockObserver(std::string name, Secretary* sub);
	~StockObserver(void);

	void Update(void);
private:
	StockObserver(void);
};

 

#include "StockObserver.h"
#include <iostream>
#include "secretary.h"

StockObserver::StockObserver(void)
{
}

StockObserver::~StockObserver(void)
{
}

StockObserver::StockObserver(std::string name, Secretary* sub)
	:Observer(name, sub)
{
}

void StockObserver::Update(void)
{
	std::string str = m_pSecretary->GetSecretaryAction();
	std::cout << m_name 
		<< str <<"please stop Looking Stock"
		<< std::endl;
}


最后是Main函数:

#include "Secretary.h"
#include "StockObserver.h"
#include "NBAObserver.h"

int main(int argc, char* argv[])
{
	Secretary* tongzhizhe = new Secretary();

	Observer* workmate1 = new NBAObserver("A ", tongzhizhe);
	Observer* workmate2 = new StockObserver("B ", tongzhizhe);

	tongzhizhe->Attach(workmate1);
	tongzhizhe->Attach(workmate2);

	tongzhizhe->SetSecretaryAction("Boss is coming back");
	tongzhizhe->Notify();

	delete tongzhizhe;
	delete workmate1;
	delete workmate2;
	return 0;
}

3.(14.4 解耦实践二)具体的通知者类可能是前台,也可能是老板,他们也许有各自的一些方法,但对于通知者来说,他们是一样的,所以他们都去实现这个接口。
4.(14.5)观察者模式又叫做发布订阅模式(Publish/Subscribe)。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

subject.h:

#pragma once
#include <string>
#include <list>
//通知者対象
class Observer;
class Subject
{
public:
	Subject(void){};
	~Subject(void){};
public:
	//增加
	virtual void Attach(Observer* pObs) = 0;
	//减少
	virtual void Detach(Observer* pObs) = 0;
	//通知
	virtual void Notify(void) = 0;
	//得到对象的状态
	virtual std::string GetSubjectState(void) = 0;
	//设置对象的状态
	virtual void SetSubjectState(std::string) = 0;
protected:
	//通知者的LIST
	std::list<Observer*> m_Observer;
	//动作
	std::string m_action;
};

Secretary.h:在这里他继承了Subject类。

#pragma once
#include "subject.h"

class Secretary : public Subject
{
public:
	Secretary(void);
	~Secretary(void);
public:
	void Attach(Observer* pObs);
	void Detach(Observer* pObs);
	void Notify(void);
	std::string GetSubjectState(void);
	void SetSubjectState(std::string);
};

Observer.h:抽象的观察者

#pragma once
#include <string>
//观察者在这里只要引用Subject的类就可以了,因为在这里已经抽象化了。
class Subject;
class Observer
{
public:
	Observer(std::string name, Subject* sub)
	{
		this->m_name = name;
		this->m_pSubject = sub;
	};
	virtual ~Observer(void){};

	virtual void Update(void){};
protected:
	std::string m_name;
	Subject* m_pSubject;
//private:
	Observer(void){};
};

NBAObserver类:

#pragma once
#include "observer.h"

class NBAObserver : public Observer
{
public:
	NBAObserver(std::string name, Subject* sub);
	~NBAObserver(void);

	void Update(void);
private:
	NBAObserver(void);
};
#include "NBAObserver.h"
#include <iostream>
#include "secretary.h"

NBAObserver::NBAObserver(void)
{
}

NBAObserver::~NBAObserver(void)
{
}

NBAObserver::NBAObserver(std::string name, Subject* sub)
:Observer(name, sub)
{
}
void NBAObserver::Update(void)
{
	std::string str = m_pSubject->GetSubjectState();
	std::cout << m_name 
		<< str <<"please stop Watching NBA"
		<< std::endl;
}

StockObserver类:

#pragma once
#include "observer.h"

class StockObserver : public Observer
{
public:
	StockObserver(std::string name, Subject* sub);
	~StockObserver(void);

	void Update(void);
private:
	StockObserver(void);
};
#include "StockObserver.h"
#include <iostream>
#include "secretary.h"

StockObserver::StockObserver(void)
{
}

StockObserver::~StockObserver(void)
{
}

StockObserver::StockObserver(std::string name, Subject* sub)
	:Observer(name, sub)
{
}

void StockObserver::Update(void)
{
	std::string str = m_pSubject->GetSubjectState();
	std::cout << m_name 
		<< str <<"please stop Looking Stock"
		<< std::endl;
}

接下来是老板BOSS类:

#pragma once
#include "subject.h"

class Boss : public Subject
{
public:
	Boss(void);
	~Boss(void);

	void Attach(Observer* pObs);
	void Detach(Observer* pObs);
	void Notify(void);
	std::string GetSubjectState(void);
	void SetSubjectState(std::string);
};
#include "Boss.h"
#include "Observer.h"

Boss::Boss(void)
{
}

Boss::~Boss(void)
{
}
void Boss::Attach(Observer* pObs)
{
	m_Observer.push_back(pObs);
}
void Boss::Detach(Observer* pObs)
{
	m_Observer.remove(pObs);
}
void Boss::Notify(void)
{
	std::list<Observer*>::const_iterator iter = m_Observer.begin();
	for (; iter != m_Observer.end(); ++iter)
	{
		(*iter)->Update();
	}
}
void Boss::SetSubjectState(std::string action)
{
	m_action = action;
}
std::string Boss::GetSubjectState(void)
{
	return m_action;
}

最后是Main函数:

#include "Secretary.h"
#include "Boss.h"
#include "StockObserver.h"
#include "NBAObserver.h"

int main(int argc, char* argv[])
{
	//boss name
	Subject* huhansan = new Boss();
	huhansan->SetSubjectState("my name is huhansan\n");

	//workmates
	Observer* workmate1 = new NBAObserver("to A: ", huhansan);
	Observer* workmate2 = new StockObserver("to B: ", huhansan);
	Observer* workmate3 = new NBAObserver("to C: ", huhansan);

	huhansan->Attach(workmate1);
	huhansan->Attach(workmate2);
	huhansan->Attach(workmate3);
	//boss is not tell workmate1 so we delete from list
	huhansan->Detach(workmate1);

	huhansan->Notify();

	delete huhansan;
	delete workmate1;
	delete workmate2;
	delete workmate3;
	return 0;
}


5.观察者模式什么时候应该使用?当一个对象的改变需要同时改变其他对象的时候。而且在不知道具体有多少个对象有待改变的时候,应该考虑使用观察者模式。
6.总的来讲,观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。这个模式也是依赖倒转原则的最佳体现。
7.将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护,扩展和重用都带来不便。
8.观察者模式的不足:在VS2005中,尽管当点击了运行按钮时,确实是在通知相关的控件产生变化,但它们是不可能用接口方式来实现观察者模式的。
9.委托就是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的类,委托的实例将代表一个具体的函数。
10.一旦为委托分配了方法,委托将于该方法具有完全相同的行为。而且,一个委托可以搭载多个方法,所有方法被依次唤起。更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。
11.有了委托以后,本来是在老板类中的增加和减少的抽象观察者集合以及通知时遍历的抽象观察者都不必要了。那就是委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的横打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值