现在的位置: 首页 > 综合 > 正文

Observer模式

2013年09月04日 ⁄ 综合 ⁄ 共 4089字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.