C++设计模式(5)——观察者模式

动机(Motivation)

  • 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对 象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

  • 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

模式定义

定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。 ——《 设计模式》 GoF

要点总结

  • 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

  • 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。即Notify会自动根据多态来调用相应的观察者

  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知。即是否需要attach新的观察者

  • Observer模式是基于事件的UI框架中常用的设计模式,也是MVC模式的一个重要组成部分。

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

非观察者模式

缺点:当需要增加新的观察者时,需修改具体的Subject中的代码,违背了开闭原则。并且其也违背了依赖倒置原则,高层模块不应该依赖于底层模块,两者都应该依赖抽象。

#include <iostream>

//观察者1
class XiaoMing 
{
public:
	void DoSomething() 
	{
		std::cout << "老师来了,停止打闹" << std::endl;
	}
};

//观察者2
class XiaoQiang 
{
public:
	void DoSomething() 
	{
		std::cout << "老师来了,可以问问题了" << std::endl;
	}
};

//具体目标
class Teacher 
{
public:
	//通知
	void Come() 
	{
		qiang.DoSomething();
		ming.DoSomething();
	}
private:
	XiaoQiang qiang;
	XiaoMing ming;
};

int main() 
{
	Teacher teacher;
	teacher.Come();
	return 0;
}

 观察者模式

#include <iostream>
//#include<algorithm>
#include <list>

//抽象类,观察者接口,收到通知用来更新观察者。
class IObserver
{
public:
	virtual void DoSomething() = 0;	//Update接口
	virtual ~IObserver()
	{
		std::cout << "~IObserver"<<std::endl;
	}
};
//观察者1
class XiaoMing : public IObserver
{
public:
	void DoSomething()
	{
		std::cout << "老师来了,停止打闹" << std::endl;
	}
};

//观察者2
class XiaoQiang : public IObserver
{
public:
	void DoSomething() 
	{
		std::cout << "老师来了,可以问问题了" << std::endl;
	}
};

//目标接口
class ISubject
{
public:
	virtual void Attach(IObserver *observer) = 0;
	virtual void Detach(IObserver *observer) = 0;
	virtual void Notify() = 0;

	virtual ~ISubject(){}
};

//具体目标
class Teacher : public ISubject
{
private:
	std::list<IObserver *> listObserver;//多个观察者,并且必须得是指针类型(多态)

public:
	//订阅,增加观察者
	void Attach(IObserver *observer)
	{
		listObserver.push_back(observer);
	}
	//删除
	void Detach(IObserver *observer)
	{
		auto itor = std::find(listObserver.begin(), listObserver.end(), observer);
		listObserver.erase(itor);
	}

	//通知
	void Notify()
	{
		for (auto observer : listObserver)
		{
			observer->DoSomething();
		}
	}
};

int main() 
{
	Teacher teacher;
	IObserver *observer1 = new XiaoMing();
	IObserver *observer2 = new XiaoQiang();
	teacher.Attach(observer1);
	teacher.Attach(observer2);
	teacher.Notify();
	teacher.Detach(observer2);
	teacher.Notify();
	delete observer1;
	delete observer2;
	observer1 = nullptr;
	observer2 = nullptr;

	return 0;
}

智能指针优化改进

#include <iostream>
//#include<algorithm>
#include <list>

//抽象类,观察者接口,收到通知用来更新观察者。
class IObserver
{
public:
	virtual void DoSomething() = 0;	//Update接口
	virtual ~IObserver()
	{
		std::cout << "~IObserver"<<std::endl;
	}
};

//观察者1
class XiaoMing : public IObserver
{
public:
	void DoSomething()
	{
		std::cout << "老师来了,停止打闹" << std::endl;
	}
};

//观察者2
class XiaoQiang : public IObserver
{
public:
	void DoSomething() 
	{
		std::cout << "老师来了,可以问问题了" << std::endl;
	}
};

//智能指针
using IObserverPtr = std::shared_ptr< IObserver>;
//目标接口
class ISubject
{
public:
	virtual void Attach(IObserverPtr observer) = 0;
	virtual void Detach(IObserverPtr observer) = 0;
	virtual void Notify() = 0;

	virtual ~ISubject(){}
};

//具体目标
class Teacher : public ISubject
{
private:
	std::list<IObserverPtr> listObserver;//多个观察者,并且必须得是指针类型(多态)

public:
	//订阅,增加观察者
	void Attach(IObserverPtr observer)
	{
		listObserver.push_back(observer);
	}
	//删除
	void Detach(IObserverPtr observer)
	{
		auto itor = std::find(listObserver.begin(), listObserver.end(), observer);
		listObserver.erase(itor);
	}

	//通知
	void Notify()
	{
		for (auto observer : listObserver)
		{
			observer->DoSomething();
		}
	}
};

int main() 
{
	Teacher teacher;
	IObserverPtr observer1 = std::make_shared<XiaoMing>();
	IObserverPtr observer2 = std::make_shared <XiaoQiang>();
	teacher.Attach(observer1);
	teacher.Attach(observer2);
	teacher.Notify();
	teacher.Detach(observer2);
	teacher.Notify();


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值