Posted on 2008-06-09 15:32
阿呆 阅读(303)
评论(0) 编辑 收藏 引用 所属分类:
设计模式学习笔记
出版者+订阅者=观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新(回调函数)。
主题(Subject)是真正拥有数据的人,观察者是主题的依赖者,在数据变化时更新,这样比起让许多对象控制同一份数据来,可以得到更干净的OO设计。
定义观察者模式:
![](http://www.cppblog.com/images/cppblog_com/adai123/ObserverMode.JPG)
当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主体和观察者之间松耦合。
改变主体或者观察者的一方,并不会影响另一方,因为两者是松耦合的,所以,只要他们之间的接口仍被遵守,我们就可以自由的改变他们。
设计原则:为了交互对象之间的松耦合设计而努力。
气象站类图:
![](http://www.cppblog.com/images/cppblog_com/adai123/WetherStation.JPG)
DefInterface.h:
1
#ifndef DEFINTERFACE_H__
2
#define DEFINTERFACE_H__
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
//-------interface definition begin---------------------------------------
5
class Observer
6![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
7
public:
8![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void Update(float temp, float humidity, float pressure)
{}
9
};
10![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
11![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
12
class DisplayElement
13![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
14
public:
15![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void Display()
{}
16
};
17![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
18
class Subject
19![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
20
public:
21![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void RegisterObserver(Observer* o)
{}
22![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void RemoveObserver(Observer* o)
{}
23![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
virtual void NotifyObserver()
{}
24
};
25
//-------interface definition End-----------------------------------------
26![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
27
#endif
DisplayBoard.h:
1
#ifndef __DISPLAYBOARD_H__
2
#define __DISPLAYBOARD_H__
3
#include "DefInterface.h"
4
class CurrentConditionDisplay : public Observer, public DisplayElement
5![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
6
public:
7
CurrentConditionDisplay(Subject* weatherdata);
8
~CurrentConditionDisplay();
9
void Update(float temp, float humidity, float pressure);
10
void Display();
11
protected:
12
private:
13
float m_tempt;
14
float m_hum;
15
float m_pres;
16
Subject* m_weatherData;
17
};
18![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
19
#endif
DisplayBoard.cpp:
1
#include "stdafx.h"
2
#include "DisplayBoard.h"
3
#include <iostream>
4
using namespace std;
5![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
6
CurrentConditionDisplay::CurrentConditionDisplay(Subject* weatherdata)
7
:m_weatherData(weatherdata), m_hum(0.0F), m_pres(0.0F), m_tempt(0.0F)
8![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
9
m_weatherData->RegisterObserver(this);
10
}
11![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
12
CurrentConditionDisplay::~CurrentConditionDisplay()
13![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
14![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
15
m_weatherData->RemoveObserver(this);
16
delete m_weatherData;
17![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
18
};
19
void CurrentConditionDisplay::Update(float temp, float humidity, float pressure)
20![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
21
m_tempt = temp;
22
m_hum = humidity;
23
m_pres = pressure;
24
Display();
25
}
26
void CurrentConditionDisplay::Display()
27![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
28
cout << "Current temperature:" << m_tempt << endl;
29
cout << "Current humidity:" << m_hum << endl;
30
cout << "Current pressure:" << m_pres << endl;
31![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
32
}
WeatherStation.h:
1
#ifndef __SUBJECT_H__
2
#define __SUBJECT_H__
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include <afxtempl.h>
5
#include "DefInterface.h"
6
//-------concrete class definition begin----------------------------------
7
class WeatherData : public Subject
8![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
9
public:
10
WeatherData();
11
~WeatherData();
12
void RegisterObserver(Observer* o);
13
void RemoveObserver(Observer* o);
14
void NotifyObservers();
15![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
16
float GetTemprature();
17
float GetHumidity();
18
float GetPressure();
19
void MeasurementsChanged();
20
void SetMeasurements(float temp, float humidity, float pressure);
21
private:
22
CArray<Observer*> m_observers;
23
float m_temperature;
24
float m_humidity;
25
float m_pressure;
26
};
27
//-------concrete class definition End------------------------------------
28
#endif
WeatherStation.cpp:
1
#include "stdafx.h"
2
#include "WeatherStation.h"
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
WeatherData::WeatherData():m_humidity(0.0F), m_pressure(0.0F), m_temperature(0.0F)/**//*,m_observers(NULL)*/
5![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
6
//m_observers = new CArray();
7
}
8![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
9
WeatherData::~WeatherData()
10![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
11
m_observers.RemoveAll();
12
}
13
void WeatherData::RegisterObserver(Observer* o)
14![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
15
m_observers.Add(o);
16
}
17![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
18
void WeatherData::RemoveObserver(Observer* o)
19![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
20
int icount = m_observers.GetCount();
21
for (int i = 0; i < icount; i++)
22![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23
if (m_observers[i] == o)
24![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
m_observers.RemoveAt(i);
26
}
27
}
28
}
29![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
30
void WeatherData::NotifyObservers()
31![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
32
int icount = m_observers.GetCount();
33
for (int i = 0; i < icount; i++)
34![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
35
Observer* observer = m_observers[i];
36
observer->Update(m_temperature, m_humidity, m_pressure);
37
}
38
}
39![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
40
float WeatherData::GetTemprature()
41![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
42
return m_temperature;
43
}
44
float WeatherData::GetHumidity()
45![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
46
return m_humidity;
47
}
48
float WeatherData::GetPressure()
49![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
50
return m_pressure;
51
}
52![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
53
void WeatherData::MeasurementsChanged()
54![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
55
NotifyObservers();
56
}
57![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
58
void WeatherData::SetMeasurements(float temp, float humidity, float pressure)
59![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
60
m_temperature = temp;
61
m_humidity = humidity;
62
m_pressure = pressure;
63
MeasurementsChanged();
64
}
65![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
66![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Test.cpp:
1
// WeatherStation_ObserverPatten.cpp : Defines the entry point for the console application.
2
//
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include "stdafx.h"
5
#include "WeatherStation.h"
6
#include "DisplayBoard.h"
7![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
8
int _tmain(int argc, _TCHAR* argv[])
9![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
10
WeatherData* wd = new WeatherData();
11
CurrentConditionDisplay* board = new CurrentConditionDisplay(wd);
12
wd->SetMeasurements(35.4, 20, 100);
13
wd->RemoveObserver(board);
14
CurrentConditionDisplay cur(wd);
15
wd->SetMeasurements(35.4, 20, 10);
16
17![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
18
return 0;
19
}
20![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
21![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)