Observer模式
观察者模式
观察/监视
软件设计的一个重要目标就是模块的高内聚,低耦合
代码设计的一个重要目标就是设计可重用的代码
在OO设计中,一个类往往包含一组成员函数和成员变量。成员变量记录类的状态,成员函数对外提供执行接口
有时候某些类的状态的改变依赖于另一个类的状态的改变
假设要设计这样一个应用:
存在类O,类C,类C的状态改变依赖类O的状态改变
一般的OO方法:
在类O中保存一个类C的指针,类O的状态改变通知类C改变状态。这样做是没有错误的
但是存在如下问题:如果我们又有一个类B,它的状态改变同样依赖类O的状态改变,OK,同理,我们在类O中同样保存一个类B的指针,O的状态改变的时候通知B改变自己的状态,如果又有了类,D,E,F……
随着依赖类的增加,类O要保存大量的类指针,O状态改变时要依次通知依赖它的每个类改变自己的状态,代码不够灵活,麻烦
更重要的是,它违背了我们一开始就提出的程序设计的一个重要的规则:高内聚,低耦合和设计可重用的代码
因为类O保存了类B,C,D,E……的指针,所以,类O不能脱离这些依赖类单独实现,我们必须在类O实现的时候定义这些依赖类的头文件(高耦合,不可重用)
Observer模式解决了这一问题
观察者模式包含了三个协作类:
客户类:即依赖于被观察类状态而改变状态的类
监视类:负责监视被观察类的状态改变,通知客户类改变自己的状态。被监视类保存监视类的指针,监视类保存所有客户类的指针(用列表保存)
被监视类:它的状态改变影响客户类的状态
用下面的代码说明(注:代码来自CodeProject)
///
// 头文件
// .h
// File : - ObserverPattern.h
// Author : - Nilesh K. Karkhanis
//
#include <list>
using namespace std;
/*==============================
* 观察者模式分析
* 被观察者 保存 一个 观察类的指针
* 观察类保存一个客户类的指针的列表数组
* 如果被观察类状态改变,将通知观察类
* 观察类依次通知客户类修改状态
================================*/
//
// Client class who is interested in getting notification
// when the observerable changes
//
//
// 客户端,观察类监视被观察类的改变,修改客户端状态
//
class Client
{
public:
Client() { cout << endl << "C'tor Client"; }
~Client() { cout << endl << "D'tor Client "; }
void Update() { cout << "Update" << endl; }
};
//
// Observer class which monitors the changes of observerable
// and notifies the client of any change
//
//
// 观察者,观察被观察类的改变
//
class Observer
{
public:
Observer() { cout << endl << "C'tor Observer ";myClient.erase(myClient.begin(), myClient.end()); }
~Observer();
bool Attach(Client* );
bool Detach(Client* );
void Notify( );
private:
list<Client*> myClient;
};
//
// Class that is to be observered
//
//
// 被观察者
//
class Observerable
{
public:
Observerable() { cout << endl << "C'tor Observerable "; myObserver = NULL; }
~Observerable() {cout << endl << "D'tor Observerable "; }
bool SetObserver(Observer* apObserver )
{
if ( !apObserver )
return false;
myObserver = apObserver;
return true;
}
void StateChanged( )
{
cout << endl << "State Changed";
myObserver->Notify();
}
private:
Observer* myObserver;
};
// 实现文件
//.cpp
///
// File : - ObserverPattern.cpp
// Author : - Nilesh K. Karkhanis
//
/*==============================
* 观察者模式分析
================================*/
#include <stdio.h>
#include <iostream.h>
#include "ObserverPattern.h"
//
// Does the client cleanup while getting destoryed
//
Observer::~Observer()
{
cout << endl << "D'tor Observer ";
list<Client*>::iterator aIterator;
for ( aIterator = myClient.begin(); aIterator != myClient.end(); aIterator++ )
{
if ( *aIterator)
{
delete *aIterator;
*aIterator = NULL;
}
}
myClient.erase(myClient.begin(), myClient.end());
}
//
// Adds the client to the list of clients
//
bool Observer::Attach(Client* apListner )
{
if ( !apListner )
return false;
myClient.push_front ( apListner );
return true;
}
//
// Removes the client from the list
//
bool Observer::Detach(Client* apListner )
{
if ( !apListner )
return false;
list<Client*>::iterator aIterator;
for ( aIterator = myClient.begin(); aIterator != myClient.end(); aIterator++ )
{
if ( *aIterator == apListner )
{
delete *aIterator;
*aIterator = NULL;
}
}
return true;
}
//
// Updates the clients when notified
//
void Observer::Notify( )
{
list<Client*>::iterator aIterator;
for ( aIterator = myClient.begin(); aIterator != myClient.end(); aIterator++ )
{
if ( *aIterator)
{
(*aIterator)->Update();
}
}
}
int main()
{
Observer* myObserver = new Observer();
Observerable* myObserverable = new Observerable();
// set the observer in the observerable class
// which allows to notiy the clients whenever there
// is any change in the observerable class
if ( !myObserverable->SetObserver( myObserver ) )
{
cout << "Could not set the observer" << endl;
return 1;
}
// Attach the clients to the observers
for ( int i = 0; i<= 5; i++ )
{
Client* aClient = new Client();
if ( !myObserver->Attach(aClient) )
{
cout << "Could not attach" << endl;
return 1;
}
}
// change the state
myObserverable->StateChanged();
delete myObserverable;
delete myObserver;
return 0;
}