中国 - 喜马拉雅

       Let life be beautiful like summer flowers . . .

观察者(Observer)模式用于解决一个相当常见的问题:当某些其它对象改变状态时,如果一组对象需要进行相应的更新,那么应该如何处理呢?这可以在“文档-视图设计模式”中见到。假定有一些数据(即“文档”)和两个视图:一个图形视图和一个文本视图。在更改“文档”数据时,必须通知这些视图更新他们自身,这就是观察者模式所要完成的任务。

// Observer.h
// The Observer interface.
#ifndef OBSERVER_H
#define OBSERVER_H

class Observable;
class Argument {};

class Observer {
public:
	// Called by the observed object, whenever
	// the observed object is changed:
	virtual void update(Observable* o, Argument* arg) = 0;
	virtual ~Observer() {}
};
#endif

“被观察”对象是Observable类型:

// Observable.h
// The Observable class.
#ifndef OBSERVABLE_H
#define OBSERVABLE_H
#include <set>
#include "Observer.h"

class Observable {
	bool changed;
	std::set<Observer*> observers;
protected:
	virtual void setChanged() { changed = true; }
	virtual void clearChanged() { changed = false; }
public:
	virtual void addObserver(Observer& o) {
		observers.insert(&o);
	}
	virtual void deleteObserver(Observer& o) {
		observers.erase(&o);
	}
	virtual void deleteObservers() {
		observers.clear();
	}
	virtual int countObservers() {
		return observers.size();
	}
	virtual bool hasChanged() { return changed; }
	// If this object has changed, notify all
	// of its observers:
	virtual void notifyObservers(Argument* arg = 0) {
		if(!hasChanged()) return;
		clearChanged(); // Not "changed" anymore
		std::set<Observer*>::iterator it;
		for(it = observers.begin();it != observers.end(); it++)
			(*it)->update(this, arg);
	}
	virtual ~Observable() {}
};
#endif // OBSERVABLE_H

具备了Observer和Obserable头文件和内部类方法的知识,现在请看一个观察者模式程序的例子。在这个例子中,被观者是花,观察者是蜜蜂和蜂鸟。花的开闭状态的变化会引起蜜蜂和蜂鸟行为的变化。

#include "stdafx.h"
// ObservedFlower.cpp
// Demonstration of "observer" pattern.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include "Observable.h"
using namespace std;

class Flower {
	bool isOpen;
public:
	Flower() : isOpen(false),
		openNotifier(this), closeNotifier(this) {}
	void open() { // Opens its petals
		isOpen = true;
		openNotifier.notifyObservers();
		closeNotifier.open();
	}
	void close() { // Closes its petals
		isOpen = false;
		closeNotifier.notifyObservers();
		openNotifier.close();
	}
	// Using the "inner class" idiom:
	class OpenNotifier;
	friend class Flower::OpenNotifier;
	class OpenNotifier : public Observable {
		Flower* parent;
		bool alreadyOpen;
	public:
		OpenNotifier(Flower* f) : parent(f),
			alreadyOpen(false) {}
		void notifyObservers(Argument* arg = 0) {
			if(parent->isOpen && !alreadyOpen) {
				setChanged();
				Observable::notifyObservers();
				alreadyOpen = true;
			}
		}
		void close() { alreadyOpen = false; }
	} openNotifier;
	class CloseNotifier;
	friend class Flower::CloseNotifier;
	class CloseNotifier : public Observable {
		Flower* parent;
		bool alreadyClosed;
	public:
		CloseNotifier(Flower* f) : parent(f),
			alreadyClosed(false) {}
		void notifyObservers(Argument* arg = 0) {
			if(!parent->isOpen && !alreadyClosed) {
				setChanged();
				Observable::notifyObservers();
				alreadyClosed = true;
			}
		}
		void open() { alreadyClosed = false; }
	} closeNotifier;
};

class Bee {
	string name;
	// An "inner class" for observing openings:
	class OpenObserver;
	friend class Bee::OpenObserver;
	class OpenObserver : public Observer {
		Bee* parent;
	public:
		OpenObserver(Bee* b) : parent(b) {}
		void update(Observable*, Argument *) {
			cout << "Bee " << parent->name
				<< "'s breakfast time!" << endl;
		}
	} openObsrv;
	// Another "inner class" for closings:
	class CloseObserver;
	friend class Bee::CloseObserver;
	class CloseObserver : public Observer {
		Bee* parent;
	public:
		CloseObserver(Bee* b) : parent(b) {}
		void update(Observable*, Argument *) {
			cout << "Bee " << parent->name
				<< "'s bed time!" << endl;
		}
	} closeObsrv;
public:
	Bee(string nm) : name(nm),
		openObsrv(this), closeObsrv(this) {}
	Observer& openObserver() { return openObsrv; }
	Observer& closeObserver() { return closeObsrv;}
};

class Hummingbird {
	string name;
	class OpenObserver;
	friend class Hummingbird::OpenObserver;
	class OpenObserver : public Observer {
		Hummingbird* parent;
	public:
		OpenObserver(Hummingbird* h) : parent(h) {}
		void update(Observable*, Argument *) {
			cout << "Hummingbird " << parent->name
				<< "'s breakfast time!" << endl;
		}
	} openObsrv;
	class CloseObserver;
	friend class Hummingbird::CloseObserver;
	class CloseObserver : public Observer {
		Hummingbird* parent;
	public:
		CloseObserver(Hummingbird* h) : parent(h) {}
		void update(Observable*, Argument *) {
			cout << "Hummingbird " << parent->name
				<< "'s bed time!" << endl;
		}
	} closeObsrv;
public:
	Hummingbird(string nm) : name(nm),
		openObsrv(this), closeObsrv(this) {}
	Observer& openObserver() { return openObsrv; }
	Observer& closeObserver() { return closeObsrv;}
};

int main() {
	Flower f;
	Bee ba("A"), bb("B");
	Hummingbird ha("A"), hb("B");
	f.openNotifier.addObserver(ha.openObserver());
	f.openNotifier.addObserver(hb.openObserver());
	f.openNotifier.addObserver(ba.openObserver());
	f.openNotifier.addObserver(bb.openObserver());
	f.closeNotifier.addObserver(ha.closeObserver());
	f.closeNotifier.addObserver(hb.closeObserver());
	f.closeNotifier.addObserver(ba.closeObserver());
	f.closeNotifier.addObserver(bb.closeObserver());
	// Hummingbird B decides to sleep in:
	f.openNotifier.deleteObserver(hb.openObserver());
	// Something changes that interests observers:
	f.open();
	f.open(); // It's already open, no change.
	// Bee A doesn't want to go to bed:
	f.closeNotifier.deleteObserver(
		ba.closeObserver());
	f.close();
	f.close(); // It's already closed; no change
	f.openNotifier.deleteObservers();
	f.open();
	f.close();
}

选自《C++编程思想》。

posted on 2012-10-05 17:42  chinaxmly  阅读(304)  评论(0编辑  收藏  举报