您的位置:首页 > 其它

设计模式之观察者模式(Observer)摘录

2014-06-26 21:42 309 查看
23种GOF设计模式一般分为三大类:创建型模式、结构型模式、行为模式。
创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。创建型模式有两个不断出现的主旋律。第一,它们都将关于该系统使用哪些具体的类的信息封装起来。第二,它们隐藏了这些类的实例是如何被创建和放在一起的。整个系统关于这些对象所知道的是由抽象类所定义的接口。因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以及何时创建这些方面给予了很大的灵活性。它们允许用结构和功能差别很大的“产品”对象配置一个系统。配置可以是静态的(即在编译时指定),也可以是动态的(在运行时)。
结构型模式涉及到如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。
行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的复杂的控制流。它们将用户的注意力从控制流转移到对象间的联系方式上来。行为类模式使用继承机制在类间分派行为。行为对象模式使用对象复合而不是继承。一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象都无法单独完成的任务。
创建型模式包括:1、FactoryMethod(工厂方法模式);2、Abstract Factory(抽象工厂模式);3、Singleton(单例模式);4、Builder(建造者模式、生成器模式);5、Prototype(原型模式).
结构型模式包括:6、Bridge(桥接模式);7、Adapter(适配器模式);8、Decorator(装饰模式);9、Composite(组合模式);10、Flyweight(享元模式);11、Facade(外观模式);12、Proxy(代理模式).
行为模式包括:13、TemplateMethod(模板方法模式);14、Strategy(策略模式);15、State(状态模式);16、Observer(观察者模式);17、Memento(备忘录模式);18、Mediator(中介者模式);19、Command(命令模式);20、Visitor(访问者模式);21、Chain of Responsibility(责任链模式);22、Iterator(迭代器模式);23、Interpreter(解释器模式).
Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言, Decorator模式比生成子类方式更为灵活。Composite:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。Flyweight:运用共享技术有效地支持大量细粒度的对象。Facade:为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
Proxy:为其他对象提供一个代理以控制对这个对象的访问。
Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
Iterator:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
Observer:(1)、意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
(2)、适用性:A、当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。B、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。C、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
(3)、优缺点:A、目标和观察者间的抽象耦合:一个目标所知道的仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。目标不知道任何一个观察者属于哪一个具体的类。这样目标和观察者之间的耦合是抽象的和最小的。因为目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次。一个处于较低层次的目标对象可与一个处于较高层次的观察者通信并通知它,这样就保持了系统层次的完整。如果目标和观察者混在一块,那么得到的对象要么横贯两个层次(违反了层次性),要么必须放在这两层的某一层中(这可能会损害层次抽象)。B、支持广播通信:不像通常的请求,目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该目标对象登记的有关对象。目标对象并不关心到底有多少对象对自己感兴趣;它唯一的责任就是通知它的各观察者。这给了你在任何时刻增加和删除观察者的自由。处理还是忽略一个通知取决于观察者。C、意外的更新:因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常很难捕捉。简单的更新协议不提供具体细节说明目标中什么被改变了,这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。
(4)、相关模式:A、Mediator:通过封装复杂的更新语义,ChangeManager(当目标和观察者间的依赖关系特别复杂时,可能需要一个维护这些关系的对象。我们称这样的对象为更改管理器。它的目的是尽量减少观察者反映其目标的状态变化所需的工作量) 充当目标和观察者之间的中介者。B、Singleton:ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。
(5)、观察者模式:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。
(6)、Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个”一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析的时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一关问题。
示例代码1:
#include <string>
#include <iostream>
#include <vector>

using namespace std;

class Secretary;

//看股票的同事类(观察对象,观察者)
class StockObserver
{
private:
	string name;
	Secretary* sub;
public:
	StockObserver(string strname, Secretary* strsub)
	{
		name = strname;
		sub = strsub;
	}

	void Update();
};

//秘书类(主题对象,通知者)
class Secretary
{
private:
	vector<StockObserver> observers;
public:
	string action;
	void Add(StockObserver ob)
	{
		observers.push_back(ob);
	}

	void Notify()
	{
		vector<StockObserver>::iterator p = observers.begin();
		
		while (p != observers.end())
		{
			(*p).Update();
			p ++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<",不要玩股票了,要开始工作了"<<endl;
}

//客户端
int main()
{
	Secretary* p = new Secretary();//创建通知者

	//观察者
	StockObserver* s1 = new StockObserver("小李", p);
	StockObserver* s2 = new StockObserver("小赵", p);

	//加入通知队列
	p->Add(*s1);
	p->Add(*s2);

	//事件
	p->action = "老板来了";

	//通知
	p->Notify();

	/*result
		小李:老板来了,不要玩股票了,要开始工作了
		小赵:老板来了,不要玩股票了,要开始工作了
	*/
		
	return 0;
}

示例代码2:
#include <string>
#include <iostream>
#include <vector>

using namespace std;

class SecretaryBase;

//抽象观察者
class CObserverBase
{
protected:
	string name;
	SecretaryBase* sub;
public:
	CObserverBase(string strname, SecretaryBase* strsub)
	{
		name = strname;
		sub = strsub;
	}

	virtual void Update() = 0;
};

//具体的观察者,看股票的
class StockObserver : public CObserverBase
{
public:
	StockObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub)
	{

	}

	virtual void Update();
};

//具体观察者,看NBA的
class NBAObserver : public CObserverBase
{
public:
	NBAObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub)
	{

	}

	virtual void Update();
};

//抽象通知者
class SecretaryBase
{
public:
	string action;
	vector<CObserverBase*> observers;
public:
	virtual void Attach(CObserverBase* observer) = 0;
	virtual void Notify() = 0;
};

//具体通知者
class Secretary : public SecretaryBase
{
public:
	void Attach(CObserverBase* ob)
	{
		observers.push_back(ob);
	}

	void Notify()
	{
		vector<CObserverBase*>::iterator p = observers.begin();

		while (p != observers.end())
		{
			(*p)->Update();
			p ++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<"不要玩股票了,要开始工作了"<<endl;
}

void NBAObserver::Update()
{
	cout<<name<<":"<<sub->action<<"不要看NBA了,老板来了"<<endl;
}

//客户端
int main()
{
	SecretaryBase* p = new Secretary();//创建观察者

	//被观察的对象
	CObserverBase* s1 = new NBAObserver("小李", p);
	CObserverBase* s2 = new StockObserver("小赵", p);
	//加入观察队列
	p->Attach(s1);
	p->Attach(s2);
	//事件
	p->action = "老板来了";
	//通知
	p->Notify();

	/*result
		小李:老板来了不要看NBA了,老板来了
		小赵:老板来了不要玩股票了,要开始工作了
	*/

	return 0;
}

示例代码3:
Subject.h:
#ifndef _SUBJECT_H_
#define _SUBJECT_H_

#include <list>
#include <string>

using namespace std;

typedef string State;

class Observer;

class Subject
{
public:
	virtual ~Subject();
	virtual void Attach(Observer* obv);
	virtual void Detach(Observer* obv);
	virtual void Notify();
	virtual void SetState(const State& st) = 0;
	virtual State GetState() = 0;
protected:
	Subject();
private:
	list<Observer*>* _obvs;
};

class ConcreteSubject : public Subject
{
public:
	ConcreteSubject();
	~ConcreteSubject();
	State GetState();
	void SetState(const State& st);
protected:
private:
	State _st;
};

#endif//~_SUBJECT_H_

Subject.cpp:
#include "Subject.h"
#include "Observer.h"

#include <iostream>
#include <list>

using namespace std;

typedef string state;

Subject::Subject()
{
	//在模板的使用之前一定要new,创建
	_obvs = new list<Observer*>;
}

Subject::~Subject()
{

}

void Subject::Attach(Observer* obv)
{
	_obvs->push_front(obv);
}

void Subject::Detach(Observer* obv)
{
	if (obv != NULL)
		_obvs->remove(obv);
}

void Subject::Notify()
{
	list<Observer*>::iterator it;

	it = _obvs->begin();

	for (; it != _obvs->end(); it ++) 
		//关于模板和iterator的用法
		(*it)->Update(this);
}

ConcreteSubject::ConcreteSubject()
{
	_st = '\0';
}

ConcreteSubject::~ConcreteSubject()
{

}

State ConcreteSubject::GetState()
{
	return _st;
}

void ConcreteSubject::SetState(const State& st)
{
	_st = st;
}

Observer.h:
#ifndef _OBSERVER_H_
#define _OBSERVER_H_

#include "Subject.h"
#include <string>

using namespace std;

typedef string State;

class Observer
{
public:
	virtual ~Observer();
	virtual void Update(Subject* sub) = 0;
	virtual void PrintInfo() = 0;
protected:
	Observer();
	State _st;
private:
};

class ConcreteObserverA : public Observer
{
public:
	virtual Subject* GetSubject();
	ConcreteObserverA(Subject* sub);
	virtual ~ConcreteObserverA();

	//传入Subject作为参数,这样可以让一个View属于多个的Subject
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

class ConcreteObserverB : public Observer
{
public:
	virtual Subject* GetSubject();
	ConcreteObserverB(Subject* sub);
	virtual ~ConcreteObserverB();
	//传入Subject作为参数,这样可以让一个View属于多个的Subject
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

#endif//~_OBSERVER_H_

Observer.cpp:
#include "Observer.h"
#include "Subject.h"

#include <iostream>
#include <string>

using namespace std;

Observer::Observer()
{
	_st = '\0';
}

Observer::~Observer()
{

}

ConcreteObserverA::ConcreteObserverA(Subject* sub)
{
	_sub = sub;
	_sub->Attach(this);
}

ConcreteObserverA::~ConcreteObserverA()
{
	_sub->Detach(this);

	if (_sub != 0)
		delete _sub;
}

Subject* ConcreteObserverA::GetSubject()
{
	return _sub;
}

void ConcreteObserverA::PrintInfo()
{
	cout<<"ConcreteObserverA observer ..."<<_sub->GetState()<<endl;
}

void ConcreteObserverA::Update(Subject* sub)
{
	_st = sub->GetState();
	PrintInfo();
}

ConcreteObserverB::ConcreteObserverB(Subject* sub)
{
	_sub = sub;
	_sub->Attach(this);
}

ConcreteObserverB::~ConcreteObserverB()
{
	_sub->Detach(this);

	if (_sub != 0)
		delete _sub;
}

Subject* ConcreteObserverB::GetSubject()
{
	return _sub;
}

void ConcreteObserverB::PrintInfo()
{
	cout<<"ConcreteObserverB observer ..."<<_sub->GetState()<<endl;
}

void ConcreteObserverB::Update(Subject* sub)
{
	_st = sub->GetState();
	PrintInfo();
}

main.cpp:
#include "Subject.h"
#include "Observer.h"

#include <iostream>

using namespace std;

int main()
{
	ConcreteSubject* sub = new ConcreteSubject();
	Observer* o1 = new ConcreteObserverA(sub);
	Observer* o2 = new ConcreteObserverB(sub);
	sub->SetState("old");
	sub->Notify();
	sub->SetState("new");//也可以由Observer调用
	sub->Notify();

	/*result
		ConcreteObserverB observer ...old
		ConcreteObserverA observer ...old
		ConcreteObserverB observer ...new
		ConcreteObserverA observer ...new
	*/

	return 0;
}

观察者模式结构图:



参考文献:
1、《大话设计模式C++》

2、《设计模式精解----GoF23种设计模式解析》
3、《设计模式----可复用面向对象软件的基础》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: