文章目录

观察者模式(大话设计模式):(又叫发布-订阅模式)

观察者模式(大话设计模式)–>事件委托C++实现


观察者模式(大话设计模式):(又叫发布-订阅模式)

  • 这是一个有意思的模式

  • 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己

  • 将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性,我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便

  • 当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少的对象有待改变,应该考虑使用观察者模式。

  • 当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将两者封装在独立的对象中使它们各自独立的改变和复用。

  • 观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象而不是依赖于具体,从而使各自的变化都不会影响另一边的变化

#include <iostream>
#include <string>
#include <list>
#include <memory>
using namespace std;
 
class Observer//抽象观察者
{
public:
	Observer() {}
	virtual ~Observer() = 0 {}
	virtual void Update() = 0;
};
class Subject//主题/抽象统治者
{
private:
	list<shared_ptr<Observer>> observers;
public:
	Subject() {}
	virtual ~Subject() = 0 {}
	//增加观察者
	void Attach(shared_ptr<Observer> observer)
	{
		observers.push_back(observer);
	}
	//移除观察者
	void Detach(shared_ptr<Observer> observer)
	{
		observers.remove(observer);
	}
	//通知
	void Notify()
	{
		for (shared_ptr<Observer> var :observers)
		{
			var->Update();
		}
	}
};
 
//具体的通知者
class ConcreteSubject :public Subject
{
private:
	//具体被观察者的状态
	string subjectState;
public:
	ConcreteSubject()
	{}
	~ConcreteSubject()
	{}
	void setState(string stat)
	{
		subjectState = stat;
	}
	string& SubjectState()
	{
		return subjectState;
	}
};
//具体的观察者
class ConcreteObserver :public Observer
{
private:
 
	string name;
	string observerState;
	shared_ptr<ConcreteSubject> subject;
public:
	ConcreteObserver(string _name, string _obs, shared_ptr<ConcreteSubject> _sub):
		name(_name), observerState(_obs), subject(_sub)
	{}
	// 通过 Observer 继承
	virtual void Update()
	{
		observerState = subject->SubjectState();
		cout << "观察者: " << name << " 的新状态是: " << subject->SubjectState() << endl;
	}
};
int main()
{
	shared_ptr<ConcreteSubject> s(new ConcreteSubject());
	s->setState(string("新状态ABC"));
 
	shared_ptr<ConcreteObserver> cc1(new ConcreteObserver(string("Name1"), string("状态A"), s));
	shared_ptr<ConcreteObserver> cc2(new ConcreteObserver(string("Name2"), string("状态B"), s));
	shared_ptr<ConcreteObserver> cc3(new ConcreteObserver(string("Name3"), string("状态C"), s));
 
	s->Attach(cc1);
	s->Attach(cc2);
	s->Attach(cc3);
 
	s->Notify();
 
	
 
	system("pause");
	return 0;
}

观察者模式(大话设计模式)–>事件委托C++实现

书中描述如下:

  • 委托就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有相同的行为委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看做是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。

  • 一个委托可以搭载多个方法,所有的方法被依次唤起

  • 可以使委托对象所搭载的方法并不需要属于同一个类(个人认为这句话是重点!重点!)

大话这本书中的例子不是c++的,关于事件委托的实现我想了个办法。其中有一些问题,比如如何实现事件委托的对象,我第一个想到的是容器存储函数指针,但是成员函数指针貌似不能用啊,然后这几天看effective c++看到了bind,这个自从学了就没用过的技能,算是大致上实现了。

这个例子中,委托对象搭载的方法不属于一个类,甚至没有任何的联系,而且只是普通的成员函数,只是方法原型长得一样。

#include <iostream>
#include <string>
#include <functional>
#include <list>
using namespace std;
 
typedef function<void()> Action;
 
class ObserverA//观察者类A
{
public:
	ObserverA() {}
	virtual ~ObserverA() {}
	virtual void ToStatusA()
	{
		cout << "执行动作A" << endl;
	}
};
class ObserverB//观察者类B
{
public:
	ObserverB() {}
	virtual ~ObserverB() {}
	virtual void ToStatusB()
	{
		cout << "执行动作B" << endl;
	}
};
class Subject//主题/通知者
{
private:
	list<Action*> acts;
public:
	Subject() {}
	virtual ~Subject() {}
 
	//注册事件
	void regist(Action *a)
	{
		acts.push_back(a);
	}
 
	//注销事件
	void unregist(Action *a)
	{
		acts.remove(a);
	}
 
	void Notify()
	{
		for (auto act : acts)
		{
			(*act)();
		}
	}
};
 
 
int main()
{
	ObserverA a;
	Action acA = bind(&ObserverA::ToStatusA, &a);
 
	ObserverB b;
	Action acB = bind(&ObserverB::ToStatusB, &b);
 
	Subject s;
 
	s.regist(&acA);
	s.regist(&acB);
	s.Notify();
 
	cout << "-----分割线-----" << endl;
 
	s.unregist(&acA);
	s.Notify();
 
	getchar();
	return 0;
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐