《大话设计模式》C++实现:14 观察者模式(一)

1、什么是观察者模式?

观察者模式,又称 “发布-订阅” (Publish-Subscribe)模式。
观察者模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象。这个主体对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

2、为何要使用观察者模式?

1、为了解耦。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。同时也满足"依赖倒转" 原则:让程序都依赖抽象,而不是相互依赖。
2、使用观察者模式的动机:
将一个系统分割成一系列互相协作的类有一个很不好的副作用:需要维护相关对象间的一致性。
我们不希望为了维护一致性而使得各类紧密耦合,这样,会给维护、扩展和重用都带来不便。
3、使用场景
(1)当一个对象的改变需要同时改变其他对象,且他不知道具体有多少个对象有待改变时,应该考虑使用观察者模式。
(2)换言之,一个抽象模型有两个方面,其中一方面依赖于另一方面,此时,用观察者模式可以将这两者凡转载独立的对象中,使他们各自独立地改变和复用。

3、如何才能用好观察者模式?

需要练习。。。

4、怎样使用观察者模式?
4.1 观察者模式的演进
  1. 双向耦合
    在这里插入图片描述
  2. 单向解耦(解耦 具体观察者与 通知者)
    在这里插入图片描述
  3. 双向解耦(解耦 具体观察者 与 具体通知者)
    (1)ISubject类:把所有观察者对象的引用(或指针),保存在一个聚集里,每个主题都可以有任何数量的观察者。 抽象主题提供一个接口,可以增加和删除观察者对象。
    (2)IObserver类:抽象观察者,为所有具体观察者定义一个接口,在得到主题的通知时,更新自己。
    (3)ConcreteSubject类:具体主题,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
    (4)ConcreteObserver类:具体观察者,实现抽象观察者角色所要求的更新接口,一遍使本身的状态与主题的状态相协调/一致。
    在这里插入图片描述
5、实例

1、双向耦合

1.1.1 Secretary.h

#pragma once
#include <list>
#include <string>
#include "StockObserver.h"
using namespace std;

class StockObserver;

class Secretary
{
public:
	Secretary();
	Secretary(const string& act) :m_sAction(act) {}
	~Secretary();
public:
	//增加
	void attach(StockObserver* observer);
	//通知
	void notify();
	//前台状态
	string getAction();
	void setAction(const string& _action);
private:
	//同事列表
	list<StockObserver* > m_observers;
	//前台状态
	string m_sAction;
};

1.1.2 Secretary.cpp

#include "Secretary.h"


Secretary::Secretary()
{
}

Secretary::~Secretary()
{
}

void Secretary::attach(StockObserver* observer)
{
	m_observers.push_back(observer);
}

void Secretary::notify()
{
	for each (StockObserver* observer in m_observers)
	{
		observer->update();
	}
}

std::string Secretary::getAction()
{
	return m_sAction;
}

void Secretary::setAction(const string& _action)
{
	m_sAction = _action;
}

1.2.1 StockObserver.h

#pragma once
#include <list>
#include <string>
#include "Secretary.h"
using namespace std;

class Secretary;
class StockObserver
{
public:
	StockObserver();
	StockObserver(const string& name, Secretary* sub);
	void update();
private:
	string m_name;
	Secretary* m_sub;
};

1.2.2 StockObserver.cpp

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


StockObserver::StockObserver()
{
}


StockObserver::StockObserver(const string& name, Secretary* sub)
	: m_name(name), m_sub(sub)
{

}

void StockObserver::update()
{
	//err: getAction没起作用,不知道原因!!
	//还真是需要指针,指针指的对象永远可以知晓
	cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}

1.3 main.cpp

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

int main()
{
	Secretary* pSecretary = new Secretary();

	StockObserver* pObserver1 = new StockObserver("小白", pSecretary);
	StockObserver* pObserver2 = new StockObserver("小黄", pSecretary);

	pSecretary->attach(pObserver1);
	pSecretary->attach(pObserver2);

	pSecretary->setAction("老板回来了");
	pSecretary->notify();

	//析构指针对象
	delete pSecretary;
	pSecretary = nullptr;
	
	delete pObserver1;
	pObserver1 = nullptr;
	delete pObserver2;
	pObserver2 = nullptr;

	system("pause");
	return 0;
}
//此种模式,
//双向耦合(Secretary依赖StockObserver,且StockObserver同时也依赖Secretary),不好!!

在这里插入图片描述
2、单向解耦(解耦 具体观察者与 通知者)
2.1.1 IObserver.h

#pragma once

#include <list>
#include <string>
#include "Secretary.h"
class Secretary;
using namespace std;

class IObserver
{
public:
	IObserver();
	IObserver(const string& name, Secretary* sub);
	virtual void update() = 0;
protected:
	string m_name;
	Secretary* m_sub;
};

2.1.2 IObserver.cpp

#include "IObserver.h"

IObserver::IObserver()
{
}

IObserver::IObserver(const string& name, Secretary* sub)
	:m_name(name), m_sub(sub)
{

}

2.2.1 StockObserver.h

#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;

class Secretary;
class StockObserver :public IObserver
{
public:
	StockObserver();
	StockObserver(const string& name, Secretary* sub);
	void update();
};

2.2.2 StockObserver.cpp

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


StockObserver::StockObserver()
{
}


StockObserver::StockObserver(const string& name, Secretary* sub)
	: IObserver(name, sub)
{

}

void StockObserver::update()
{
	//err: getAction没起作用,不知道原因!!
	//还真是需要指针,指针指的对象永远可以知晓
	cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}

2.3.1 NBAObserver.h

#pragma once
#include "IObserver.h"
class NBAObserver :
	public IObserver
{
public:
	NBAObserver();
	NBAObserver(const string& name, Secretary* sub);
	virtual void update() override;
};

2.3.2 NBAObserver.cpp

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


NBAObserver::NBAObserver()
{
}


NBAObserver::NBAObserver(const string& name, Secretary* sub)
	:IObserver(name, sub)
{

}

void NBAObserver::update()
{
	cout << m_sub->getAction() << "," << m_name << ", 关闭NBA直播,继续工作!" << endl;
}

2.4.1 Secretary.h

#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;

class IObserver;
class Secretary
{
public:
	Secretary();
	Secretary(const string& act) :m_sAction(act) {}
public:
	//增加
	void attach(IObserver* observer);
	void detach(IObserver* observer);
	//通知
	void notify();
	//前台状态
	string getAction();
	void setAction(const string& _action);
private:
	//同事列表
	list<IObserver* > m_observers;
	//前台状态
	string m_sAction;
};

2.4.2 Secretary.cpp

#include "Secretary.h"


Secretary::Secretary()
{
}

void Secretary::attach(IObserver* observer)
{
	m_observers.push_back(observer);
}

void Secretary::detach(IObserver* observer)
{
	m_observers.remove(observer);
	delete observer;
	observer = nullptr;
}

void Secretary::notify()
{
	for each (IObserver* observer in m_observers)
	{
		observer->update();
	}
}

std::string Secretary::getAction()
{
	return m_sAction;
}

void Secretary::setAction(const string& _action)
{
	m_sAction = _action;
}

2.5 main.cpp

#include<iostream>
#include "Secretary.h"
#include "StockObserver.h"
#include "NBAObserver.h"

void test2()
{
	cout << "==============test2()=================" << endl;
	Secretary* pSecretary = new Secretary();
	StockObserver* pObserver1 = new StockObserver("小白", pSecretary);
	NBAObserver* pObserver2 = new NBAObserver("小黄", pSecretary);

	pSecretary->attach(pObserver1);
	pSecretary->attach(pObserver2);

	pSecretary->setAction("Leo回来了");
	pSecretary->notify();

	//析构指针对象
	delete pSecretary;
	pSecretary = nullptr;

	delete pObserver1;
	pObserver1 = nullptr;
	delete pObserver2;
	pObserver2 = nullptr;
}
//此种模式,
//也存在耦合
//有一点改进:观察者稍稍解耦,可以拓展任意多个观察者

int main()
{
	test2();
	system("pause");
	return 0;
}

在这里插入图片描述
3、双向解耦(解耦 具体观察者 与 具体通知者)
3.1.1 IObserver.h

#pragma once

#include <list>
#include <string>
#include "ISubject.h"
class ISubject;
using namespace std;

class IObserver
{
public:
	IObserver();
	IObserver(const string& name, ISubject* sub);
	virtual void update() = 0;
protected:
	string m_name;
	ISubject* m_sub;
};

3.1.2 IObserver.cpp

#include "IObserver.h"
IObserver::IObserver()
{
}


IObserver::IObserver(const string& name, ISubject* sub)
	:m_name(name), m_sub(sub)
{

}

3.2.1 StockObserver .h

#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;

class Secretary;
class StockObserver :public IObserver
{
public:
	StockObserver();
	StockObserver(const string& name, ISubject* sub);
	void update()override;
};

3.2.2 StockObserver .cpp

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


StockObserver::StockObserver()
{
}


StockObserver::StockObserver(const string& name, ISubject* sub)
	: IObserver(name, sub)
{

}

void StockObserver::update()
{
	//err: getAction没起作用,不知道原因!!
	//还真是需要指针,指针指的对象永远可以知晓
	cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}

3.3.1 NBAObserver .h

#pragma once
#include "IObserver.h"
class NBAObserver :
	public IObserver
{
public:
	NBAObserver();
	NBAObserver(const string& name, ISubject* sub);
	virtual void update() override;
};

3.3.1 NBAObserver .cpp

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


NBAObserver::NBAObserver()
{
}


NBAObserver::NBAObserver(const string& name, ISubject* sub)
	:IObserver(name, sub)
{

}

void NBAObserver::update()
{
	cout << m_sub->getAction() << "," << m_name << ", 关闭NBA直播,继续工作!" << endl;
}

3.4 ISubject.h

#pragma once
#include "IObserver.h"
#include <string>
using namespace std;

class IObserver;
class ISubject
{
public:
	virtual void attach(IObserver* observer) = 0;
	virtual void detach(IObserver* observer) = 0;
	virtual void notify() = 0;
	virtual string getAction() = 0;
	virtual void setAction(const string& action) = 0;
};

3.5.1 Secretary.h

#pragma once
#include "ISubject.h"
#include <list>

class IObserver;
class Secretary :public ISubject
{
public:
	Secretary();
	Secretary(const string& act) :m_sAction(act) {}
public:
	//增加
	void attach(IObserver* observer) override;
	void detach(IObserver* observer) override;
	//通知
	void notify() override;
	//前台状态
	string getAction() override;
	void setAction(const string& _action) override;
private:
	//同事列表
	list<IObserver* > m_observers;
	//前台状态
	string m_sAction;
};

3.5.1 Secretary.cpp

#include "Secretary.h"


Secretary::Secretary()
{
}

void Secretary::attach(IObserver* observer)
{
	m_observers.push_back(observer);
}

void Secretary::detach(IObserver* observer)
{
	m_observers.remove(observer);
	delete observer;
	observer = nullptr;
}

void Secretary::notify()
{
	for each (IObserver* observer in m_observers)
	{
		observer->update();
	}
}

std::string Secretary::getAction()
{
	return m_sAction;
}

void Secretary::setAction(const string& _action)
{
	m_sAction = _action;
}

3.6.1 Boss .h

#pragma once
#include "ISubject.h"
#include <list>

class Boss :
	public ISubject
{
public:
	Boss();

	virtual void attach(IObserver* observer) override;


	virtual void detach(IObserver* observer) override;


	virtual void notify() override;


	virtual string getAction() override;


	virtual void setAction(const string& action) override;

private:
	list<IObserver* > m_observers;
	string m_action;
};

3.6.2 Boss .cpp

#include "Boss.h"



Boss::Boss()
{
}

void Boss::attach(IObserver* observer)
{
	m_observers.push_back(observer);
}

void Boss::detach(IObserver* observer)
{
	m_observers.remove(observer);
}

void Boss::notify()
{
	for each (IObserver* observer in m_observers)
	{
		observer->update();
	}
}

std::string Boss::getAction()
{
	return m_action;
}

void Boss::setAction(const string& action)
{
	m_action = action;
}

3.7 main.cpp

#include<iostream>
#include "Secretary.h"
#include "StockObserver.h"
#include "NBAObserver.h"
#include "Boss.h"

void test3()
{
	cout << "==============test3()=================" << endl;
	Boss* pBoss = new Boss();
	StockObserver* pObserver1 = new StockObserver("小白", pBoss);
	NBAObserver* pObserver2 = new NBAObserver("小黄", pBoss);

	pBoss->attach(pObserver1);
	pBoss->attach(pObserver2);

	pBoss->setAction("May I come in ?");
	pBoss->notify();

	//析构指针对象
	delete pBoss;
	pBoss = nullptr;

	delete pObserver1;
	pObserver1 = nullptr;
	delete pObserver2;
	pObserver2 = nullptr;
}
//实现了 具体观察者与具体通知者的 解耦
//之后可以随便扩展 通知者,随便扩展观察者,且每个通知者都可以与私下里与任意观察者交易,绑定与解绑,由每个通知者自己意愿决定

int main()
{
	test3();
	system("pause");
	return 0;
}

在这里插入图片描述

此为《大话设计模式》学习心得系列 P123~~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值