C++ 观察者模式 - 坚持 "Program to Interfaces" 原则
C++ Observer Patterns - Sticking to "Program to Interfaces" principal
我正在用 C++ 实现 Head First 设计模式中的观察者模式,但我遇到了一个小问题。
我收到错误:“class Subject has no member named setNewMeasurments”在 station->setNewMeasurments(0.5,10.0, 7.5);
行
看来如果我想使用多态性,应该在接口(“Subject”)中定义方法“setNewMeasurments
”。但这违反了 "Programming to Interfaces" 的原则,我真的需要多态性才能使观察者模式在这里工作。请问有什么意见吗?谢谢!!!
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
/**************************************************
*************** Interfaces ******************
***************************************************/
class Observer
{
public:
virtual void update(float temp, float humidity, float pressure) = 0 ;
};
class Subject
{
protected:
vector<Observer*> observers; //est-ce une bonne idée ici? c'est contraire au pattern strategy (separate changing elements from constant ones) -> Visiblement c'est ce qui est fait dans l'UML page 56
public:
virtual void registerObserver(Observer* o) = 0;
virtual void removeObserver(Observer* o) = 0;
virtual void notifyObserver() = 0;
};
class DisplayElement
{
public:
virtual void display() const = 0 ;
};
/**************************************************
************* Implementations ***************
***************************************************/
class WeatherData : public Subject
{
private:
float temperature;
float humidity;
float pressure;
public:
virtual void registerObserver(Observer* o){
observers.push_back(o); //y'a as un probleme la?
}
virtual void removeObserver(Observer* o){
std::vector<Observer*>::iterator position=std::find(observers.begin(), observers.end(), o);
if (position != observers.end())
observers.erase(position);
}
virtual void notifyObserver()
{
for (vector<Observer*>::iterator it=observers.begin() ; it!=observers.end() ; it++)
{
(*it)->update(temperature, humidity, pressure);
}
}
void measurmentChanged() {
notifyObserver();
}
void setNewMeasurments(float temp, float hum, float press)
{
this->temperature=temp;
this->humidity=hum;
this->pressure=press;
measurmentChanged();
}
};
class CurrentConditionsDisplay : public Observer, public DisplayElement
{
private:
float temperature;
float humidity;
float pressure;
Subject* weatherData;
// Faut penser à désallouer cette mémoire dans le destructeur --> exercice!! (le faire à la main puis utiliser le Wrapper)
public:
CurrentConditionsDisplay(Subject* w){
weatherData=w;
weatherData->registerObserver(this);
}
void update(float temp, float hum, float press){
temperature=temp;
humidity=hum;
pressure=press;
display();
}
void display() const {
cout << "Current Conditions Displayers " << endl << endl;
cout << "Temperature : " << temperature << endl;
cout << "Humidity : " << temperature << endl;
cout << "Pressure : " << temperature << endl;
};
};
int main()
{
Subject* station=new WeatherData;
CurrentConditionsDisplay mDisp(station);
station->setNewMeasurments(0.5,10.0, 7.5);
delete station;
system("PAUSE");
return 0;
}
这就是多态性的工作原理!如果您将一个对象声明为 Subject
,您只能访问 Subject
的函数及其基础 class 的函数。
如果您需要调用函数 setNewMeasurments
,您需要通过将变量 station
声明为 WeatherData
.
来使其可访问
我认为您实际想要完成的是隐藏 WeatherData
的 实现 ,而不是隐藏整个 class。您可以通过在 *.cpp 文件中移动函数实现来完成此操作。因此,您只会在 *.h 文件中包含函数定义,在 *.cpp 文件中包含实际代码。
这里的问题是当你写:
Subject* station=new WeatherData;
你告诉编译器 station
是一个 Subject,而 Subject 没有定义一个名为 setNewMeasurments
.
的函数
您必须将指针 station
转换为 WeatherData
:
((WeatherData*)station)->setNewMeasurments(0.5,10.0, 7.5);
或者如 CoffeeandCode 所指出的那样在真正的 C++ 中:
static_cast<WeatherData*>(station)->setNewMeasurments(0.5,10.0, 7.5);
但是,由于WeatherDate
继承自Subject
,你可以直接写:
WeatherData* station=new WeatherData;
CurrentConditionsDisplay mDisp(station);
station->setNewMeasurments(0.5,10.0, 7.5);
我正在用 C++ 实现 Head First 设计模式中的观察者模式,但我遇到了一个小问题。
我收到错误:“class Subject has no member named setNewMeasurments”在 station->setNewMeasurments(0.5,10.0, 7.5);
行
看来如果我想使用多态性,应该在接口(“Subject”)中定义方法“setNewMeasurments
”。但这违反了 "Programming to Interfaces" 的原则,我真的需要多态性才能使观察者模式在这里工作。请问有什么意见吗?谢谢!!!
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
/**************************************************
*************** Interfaces ******************
***************************************************/
class Observer
{
public:
virtual void update(float temp, float humidity, float pressure) = 0 ;
};
class Subject
{
protected:
vector<Observer*> observers; //est-ce une bonne idée ici? c'est contraire au pattern strategy (separate changing elements from constant ones) -> Visiblement c'est ce qui est fait dans l'UML page 56
public:
virtual void registerObserver(Observer* o) = 0;
virtual void removeObserver(Observer* o) = 0;
virtual void notifyObserver() = 0;
};
class DisplayElement
{
public:
virtual void display() const = 0 ;
};
/**************************************************
************* Implementations ***************
***************************************************/
class WeatherData : public Subject
{
private:
float temperature;
float humidity;
float pressure;
public:
virtual void registerObserver(Observer* o){
observers.push_back(o); //y'a as un probleme la?
}
virtual void removeObserver(Observer* o){
std::vector<Observer*>::iterator position=std::find(observers.begin(), observers.end(), o);
if (position != observers.end())
observers.erase(position);
}
virtual void notifyObserver()
{
for (vector<Observer*>::iterator it=observers.begin() ; it!=observers.end() ; it++)
{
(*it)->update(temperature, humidity, pressure);
}
}
void measurmentChanged() {
notifyObserver();
}
void setNewMeasurments(float temp, float hum, float press)
{
this->temperature=temp;
this->humidity=hum;
this->pressure=press;
measurmentChanged();
}
};
class CurrentConditionsDisplay : public Observer, public DisplayElement
{
private:
float temperature;
float humidity;
float pressure;
Subject* weatherData;
// Faut penser à désallouer cette mémoire dans le destructeur --> exercice!! (le faire à la main puis utiliser le Wrapper)
public:
CurrentConditionsDisplay(Subject* w){
weatherData=w;
weatherData->registerObserver(this);
}
void update(float temp, float hum, float press){
temperature=temp;
humidity=hum;
pressure=press;
display();
}
void display() const {
cout << "Current Conditions Displayers " << endl << endl;
cout << "Temperature : " << temperature << endl;
cout << "Humidity : " << temperature << endl;
cout << "Pressure : " << temperature << endl;
};
};
int main()
{
Subject* station=new WeatherData;
CurrentConditionsDisplay mDisp(station);
station->setNewMeasurments(0.5,10.0, 7.5);
delete station;
system("PAUSE");
return 0;
}
这就是多态性的工作原理!如果您将一个对象声明为 Subject
,您只能访问 Subject
的函数及其基础 class 的函数。
如果您需要调用函数 setNewMeasurments
,您需要通过将变量 station
声明为 WeatherData
.
我认为您实际想要完成的是隐藏 WeatherData
的 实现 ,而不是隐藏整个 class。您可以通过在 *.cpp 文件中移动函数实现来完成此操作。因此,您只会在 *.h 文件中包含函数定义,在 *.cpp 文件中包含实际代码。
这里的问题是当你写:
Subject* station=new WeatherData;
你告诉编译器 station
是一个 Subject,而 Subject 没有定义一个名为 setNewMeasurments
.
您必须将指针 station
转换为 WeatherData
:
((WeatherData*)station)->setNewMeasurments(0.5,10.0, 7.5);
或者如 CoffeeandCode 所指出的那样在真正的 C++ 中:
static_cast<WeatherData*>(station)->setNewMeasurments(0.5,10.0, 7.5);
但是,由于WeatherDate
继承自Subject
,你可以直接写:
WeatherData* station=new WeatherData;
CurrentConditionsDisplay mDisp(station);
station->setNewMeasurments(0.5,10.0, 7.5);