设计模式之调查者模式与其C++通用实现(上)
副标题#e#
调查者模式
意图:
界说工具间的一种一对多的依赖干系,当一个工具的状态产生改变时,所有依赖于它的工具都获得通知并被自动更新。
布局:
利益:
方针(Subject)与调查者(Observer)间抽象耦合
支持广播通信/通知
缺点:
会带来意外更新问题
示例:
思量这样一个例子:想知道公司最新的MM情报吗?插手我们MM情报邮件组吧。您只需要向我们发送一封订阅邮件即可,我们会把最新的MM情报以电子邮件形式通知您。
此刻我们来一步一步实现。很明明,示例中体贴MM环境的人物即为订阅者,我们以Subscriber暗示这一类人。在界说Subscriber之前我们先界说一个MMStatus列举,用以暗示MM状态:
1.enum MMStatus {Dining, Sleeping, Working};
这里界说了三个常量用以简朴地模仿MM所处的状态。此刻我们可以界说Subscriber类了:
1.struct Subscriber
2.{
3. virtual void action(MMStatus status) = 0;
4. virtual ~Subscriber() {}
5.};
#p#副标题#e#
有履历的读者知道,这样界说Subscriber表白它是个基类,也是个抽象类,可能称之为接口(java中就有 interface要害字)。之所以这样设计,是因为大概存在许多种范例的订阅者(Subscriber接口的子类),每种订阅者对MM的同一种状态大概会有差异的处理惩罚方法。这里把多种范例的订阅者抽象出沟通的接口要领,也就是Subscriber界说的第3行。第4行固然只是个空界说,但这是不行缺少的,防备在用基类指针指向子类而delete基类指针时子类的析构行为能正确挪用。我们继承界说我们的方针类。没错,就是MM情报组,我们以 MMIntelligenceAgent类暗示。
1.class MMInteligenceAgent
2.{
3.public:
4. void subscribe(Subscriber &subscriber);
5. void desubscribe(Subscriber &subscriber);
6.private:
7. void notifyAll(MMStatus status);
8.private:
9. std::list<Subscriber*> subscribers_;
10.};
MMInteligenceAgent类有两个公有要领(4、5行),别离用以增加和移除一个订阅者。订阅者大概有多个,我们选择以链表存储之(9行)。当MM状态改观后,借助notifyAll要领,链表中的所有订阅者城市获得通知。
方针类的实现很简朴:
1.void MMInteligenceAgent::subscribe(Subscriber &subscriber)
2.{
3. subscribers_.push_back(&subscriber);
4.}
5.
6.void MMInteligenceAgent::desubscribe(Subscriber &subscriber)
7.{
8. subscribers_.erase(
9. std::remove(subscribers_.begin(), subscribers_.end(), &subscriber),
10. subscribers_.end());
11.}
12.void MMInteligenceAgent::notifyAll(MMStatus status)
13.{
14. for (list<Subscriber*>::iterator it = subscribers_.begin();
15. it != subscribers_.end(); ++it) {
16. (*it)->action(status);
17. }
18.}
主要的基类及要领都写好了,接下来我们示例个详细Subscriber类:盗窃者。盗窃者一般在偷盗方针熟睡时较量容易下手,于是盗窃者可利用MM情报组提供的处事,以便知道MM何时在睡觉:
1.struct Larcener : public Subscriber
2.{
3. virtual void action(MMStatus status)
4. {
5. if (status == Sleeping) {
6. // steal something ...
7. }
8. }
9.};
为了使代码更完整,我们可觉得MMInteligenceAgent增加一个对MM的跟踪要领,当发明MM状态改变时发出通知。
1.void MMInteligenceAgent::trace()
2.{
3. ...
4. MMStatus status = ...;
5. notifyAll(status);
6.}
最后以一个挪用示例作为此篇的竣事:
1.int main()
2.{
3. ...
4. Larcener l;
5. MMInteligenceAgent mia;
6. mia.subscribe(l);
7. mia.trace();
8. ...
9. mia.desubscribe(l);
10. ...
11.}
<未完,待续>