设计模式:观察者模式

观察者模式有点像事件触发机制,也是一种回调机制,在观察者模式中,有观察者和被观察者,当被观察者有什么动静的时候,就可以以某种方式通知观察者做出某些动作,简单示例如下:

class Observer {
public:
	virtual void update() = 0;
};

class Observer1 : public Observer {
public:
	void update() { cout<<"Observer1 updating"<<endl; }
};

class Observable {
protected:
	list<Observer*> ls;
public:
	void addObserver(Observer *p) { ls.push_back(p); }
	void noticeObserver();
};
Observer是观察者的基类,提供一些通用接口,派生的观察者(Observer1)可以重定义这些接口来执行特定的的响应动作。Observable是被观察者,它有一个list<Observer*>用于保存那些关注着它的观察者们,这些观察者可以通过addObserver()被添加进来,如果Observable有什么动静,就可以调用noticeeObserver来通知观察者们,noticeObserver的定义如下:

void Observable::noticeObserver() {

	list<Observer*>::iterator it = ls.begin();
	while(it!=ls.end()) {
		(*it)->update();
		it++;
	}

};

在noticeObserver通过iterator一个一个地通知Observer,即调用Observer的update()。这是最简单直观的观察者模式,在《C++编程思想》中给出了一种基于内部类的观察者模式,注意这里是内部类而不是嵌套类,内部类是可以访问外围类私有成员的嵌套类,C++中没有直接支持内部类,我们可以通过简单的代码来实现一个内部类:

class Outer {
	int i;
	class Inner;
	friend class Outer::Inner;
	class Inner {
		Outer *p;
	public:
		void func() { cout<<p->i<<endl; }
	};
};
Inner保存着一个指向Outer的指针:p ,且Inner为Outer的友元,所以在Inner中可以通过p来访问Outer的私有成员(在C++中,嵌套类与外围类基本没有关系,除了嵌套类是在外围类中定义的,如果不是互为友元,外围类不可以访问嵌套类的私有成员,嵌套类也不可以访问外围类的私有成员)。下面我们基于内部类给出一个简单的事件触发机制:

class Observable {
protected:
	list<Observer*> ls;
public:
	void addObserver(Observer *p) { ls.push_back(p); }
	void noticeObserver();
};

class Event {

	bool isClicked;
	bool isDoubleClicked;
public:
	/*     Inner class : ClickEvent    */
	class ClickEvent;
	friend class Event::ClickEvent;
	class ClickEvent : public Observable {
		Event *p;
	public:
		ClickEvent(Event *q) : p(q) {}
		void noticeObserver() {
			if (!p->isClicked) return ;
			list<Observer*>::iterator it = ls.begin();
			while(it!=ls.end()) {
				(*it)->update();
				it++;
			}
			p->isClicked = false;
		}
	} clickEvent;

	/*     Inner class : DoubleClickEvent    */
	class DoubleClickEvent;
	friend class Event::DoubleClickEvent;
	class DoubleClickEvent : public Observable {
		Event *p;
	public:
		DoubleClickEvent(Event *q) : p(q) {}
		void noticeObserver() {
			if (!p->isDoubleClicked) return ;
			list<Observer*>::iterator it = ls.begin();
			while(it!=ls.end()) {
				(*it)->update();
				it++;
			}
			p->isDoubleClicked = false;
		}
	} doubleClickEvent;


	Event() : isClicked(false),isDoubleClicked(false),clickEvent(this),doubleClickEvent(this) {}
	void setClick() {
		isClicked = true;
		clickEvent.noticeObserver();
	}
	void setDoubleClick() {
		isDoubleClicked = true;
		doubleClickEvent.noticeObserver();
	}
};
代码有点长,不过很好理解,Event是事件的总称,里面既有单击事件(ClickEvent),也有双击事件(DoubleClickEvent),这两个事件都被定义成内部类(都保存一个指向Event的指针),单击事件有单击事件的Observer,双击事件有双击事件的Observer,所以如果发生了单击事件,就通知单击事件的Observer,否则通知双击事件的Observer。ClickEvent和DoubleEvent都是Observable的派生类。完整的观察者模式应该还有观察者,如下:

class Observer {
public:
	virtual void update() { cout<<"updating"<<endl; }
};

class ClickObserver: public Observer {
public:
	virtual void update() { cout<<"clicked"<<endl; }
};

class DoubleClickObserver: public Observer {
public:
	void update() { cout<<"double clicked"<<endl; }
};
即定义两个观察者,ClickObserver对单击事件感兴趣,而DoubleClickObserver对双击事件感兴趣,下面给出一个使用上述事件触发机制的例子:

int main() { 

	Event e;
	e.clickEvent.addObserver(new ClickObserver());
	e.setClick();
	e.doubleClickEvent.addObserver(new DoubleClickObserver());
	e.setDoubleClick();	
	return 0; 
}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值