观察者模式

观察者模式

  作用及特点:两个类有逻辑关系,一个类为主体,另一个类作为观察者,当主体的某一个属性发生变化时,观察者可以根据主体的属性变化做出响应, 一般来说,主体只有一个,观察者可以有好多个,是一对多的关系。
  现在马戏团要投喂动物了,假设动物食物的属性可以改变,比如战斧牛排肉很多,是老鹰喜欢吃的食物,老鹰吃完后,剩下带肉的战斧骨头,是老虎喜欢啃的食物,这里食物的属性有个变化。战斧牛排是主体,观察者是老鹰和老虎,当食物属性发生变化时,老鹰和老虎都会做出响应。

主体类

  主体类的主要函数为:增加观察者,移除观察者,通知观察者。我们需要一个vector来存储这些观察者。

«Interface»
ISubject
+void Add(IObserver* obr)
+void Remove(IObserver* obr)
+void Notify(string propertyName)
+void changeFoodProperty(string property)
AnimalFood
-vector<IObserver*> m_observers
+void Add(IObserver* obr)
+void Remove(IObserver* obr)
+void Notify(string propertyName)
+void changeFoodProperty(string property)

  接下来是主体类的详细代码:Animal.h和Animal.cpp

Animal.h

class ISubject{
public:
	virtual ~ISubject() {}
	virtual void Add(IObserver* obr) = 0;
	virtual void Remove(IObserver* obr) = 0;
	virtual void Notify(std::string propertyName) = 0;
};

class AnimalFood : public ISubject
{
public:
	virtual void Add(IObserver* obr);
	virtual void Remove(IObserver* obr);
	virtual void Notify(std::string propertyName);
	virtual void changeFoodProperty(std::string property);

	std::string m_foodProperty;

private:
	std::vector<IObserver*> m_observers;
};

Animal.cpp

void AnimalFood::Add(IObserver* obr)
{
	auto iter = std::find(m_observers.begin(), m_observers.end(), obr);
	if (iter == m_observers.end())
	{
		m_observers.emplace_back(obr);
	}
}
void AnimalFood::Remove(IObserver* obr)
{
	auto iter = std::find(m_observers.begin(), m_observers.end(), obr);
	if (iter != m_observers.end())
	{
		m_observers.erase(iter);
	}
}
void AnimalFood::Notify(std::string propertyName)
{
	for (const auto& obs : m_observers)
	{
		obs->propertyChange(propertyName);
	}
}

void AnimalFood::changeFoodProperty(std::string property)
{
	if (m_foodProperty != property)
	{
		m_foodProperty = property;
	}
	Notify("食物类型");
}

观察者类

«Interface»
IObserver
-ISubject* m_subject
+void propertyChange(string propertyName)
Tiger
-vector<IObserver*> m_observers
+void propertyChange(string propertyName)
Eagle
-vector<IObserver*> m_observers
+void propertyChange(string propertyName)
Animal
#int m_age
#string m_sex
#bool m_sick
virtual void init()
TerrestrialAnimal
#int m_weight
+virtual void running()
FlyingBird
#bool m_FreshwaterFish
+virtual void flying()
«Interface»
ISubject
+void Add(IObserver* obr)
+void Remove(IObserver* obr)
+void Notify(string propertyName)
+void changeFoodProperty(string property)

Animal.h

class IObserver
{
public:
	virtual void propertyChange(std::string propertyName) = 0;
	ISubject* m_subject = nullptr;
};

class Tiger :public TerrestrialAnimal, public IObserver//老虎类
{
public:
	Tiger(const std::string& name);
	Tiger(const std::string& name, AnimalFood* subject);
	~Tiger();
	virtual bool init(const std::string& name);
	virtual void running();
	virtual void propertyChange(std::string propertyName);
	static Tiger* New(const std::string& name);
};

class Eagle :public FlyingBird, public IObserver//老鹰类
{
public:
	Eagle(const std::string& name);
	Eagle(const std::string& name, AnimalFood* subject);
	~Eagle();
	virtual bool init(const std::string& name);
	virtual void flying();
	virtual void propertyChange(std::string propertyName);

	static Eagle* New(const std::string& name);
};

Animal.cpp

Tiger::Tiger(const std::string& name, AnimalFood* subject)
{
	init(name);
	m_subject = subject;
}

void Tiger::propertyChange(std::string propertyName)
{
	if (propertyName == "食物类型")
	{
		if (static_cast<AnimalFood*>(m_subject)->m_foodProperty == "虎类食物")
		{
			printf("我是%s,马戏团开饭了,我要吃饭!\n\n", m_name.c_str());
		}
		else
		{
			printf("我是%s,这是其它动物的食物!\n\n", m_name.c_str());
		}
	}
}

Eagle::Eagle(const std::string& name, AnimalFood* subject)
{
	init(name);
	m_subject = subject;
}

void Eagle::propertyChange(std::string propertyName)
{
	if (propertyName == "食物类型")
	{
		if (static_cast<AnimalFood*>(m_subject)->m_foodProperty == "鹰类食物")
		{
			printf("我是%s,马戏团开饭了,我要吃饭!\n\n", m_name.c_str());
		}
		else
		{
			printf("我是%s,这是其它动物的食物!\n\n", m_name.c_str());
		}
	}
}

输出结果和总结

  • 主体类,即被观察的类,需要有容器存放观察者std::vector<IObserver*> m_observers;
  • 观察者类,初始化时要记录主体类的指针,很有可能观察者要用到主体类的内容,内容包括主体类的变量和函数。
  • 主体类属性变化,通知观察者时,可以告诉观察者是哪个属性发生了变化,观察者可以根据属性,采取行动

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值