我想知道处理可能包含不同数据的Observable的适当方法是什么。要使用天气数据类比:
假设我有不同的气象站记录数据。让我们说湿度,温度和压力。一个站可能只具有记录温度的能力,而其他站三个等等。
我要做的是以下内容:
以下是一些事项:
有比3更多的参数。像30这样的东西,这可以增长。我想在我的基础可观察中实现getTemperature()
,getPressure()
,getHumidity()
等等,并在相关类中重写它们。否则它什么也不返回。我还创建了为Observable和Observer指定的Flags
匿名结构,并且只有当它们匹配数据时才会被记录。
我想知道以下内容:
这是最好的设计吗?匹配Flags
的责任应该在观察者身上吗?有更优雅的解决方案吗?
我不一定在寻找代码讲义。关于良好实施的想法。
谢谢!
答案 0 :(得分:2)
因为你已经有Flags
来识别可以观察到的东西,即
enum Measurement {
Temperature = 0x00001
, Humidity = 0x00002
, Pressure = 0x00004
};
您可以重复使用它来通过数据识别测量值,而不是通过方法名称识别它们。换句话说,而不是使界面看起来像这样
struct observable {
Measurement provides() {
return Temperature | Humidity | Pressure;
}
double getTemperature() ...
double getHumidity() ...
double getPressure() ...
};
这样做:
struct observable {
Measurement provides() {
return Temperature | Humidity | Pressure;
}
double measure(Measurement measurementId) {
...
}
};
这将为您提供统一的界面,观察者和观察者完全通过数据匹配。
但是,measure
的所有实现都需要根据看起来像switch
的数字“调度”,这是不理想的。有一个解决方案:您可以在基类中放置一个非虚拟实现,然后使用常规虚拟调度:
struct observable_base {
double measure(Measurement measurementId) {
switch(measurementId) {
case Temperature: return getTemperature();
case Humidity: return getHumidity();
case Pressure: return getPressure();
}
return 0;
}
protected:
virtual double getTemperature() { return 0; }
virtual double getHumidity() { return 0; }
virtual double getPressure() { return 0; }
};
答案 1 :(得分:1)
根据我的经验,最好为观察者模式使用面向对象的设计。
您可以创建一个Observer<天气>和一个Observable<天气>使用一个被观察的对象,一个Weather对象。伪代码样本:
public class Weather()
{
... Temperature
... Pressure
... Humidity
}
如果给定的实现具有多个可观察的数据,只需让它实现该类型的Observable。
所以,你可以有一个ColorableWeatherState对象,它同时是Observable<天气>和Observable<颜色>可以由关心色彩的观察者和关心天气的观察者订阅。他们可能是分开的。它们可能是同一个对象。由您决定实施。
答案 2 :(得分:1)
首先,以下是我的意见。有很多方法可以解决您的问题,也许其他方法更好。我告诉你我是如何解决这类问题的。
我不会用所有可能的方法定义一个基本的observable,那就是糟糕的风格。基类应该只定义方法,它才能实现。另外,它很难扩展,你必须同时编写观察者和可观察对象,并且必须对它们进行编译。如果将来使用其他通信层,如网络,则更难以抽象。
如果您的值具有相同的类型,请使用一个getter方法并为其选择一个参数来选择结果:
double getValue(enumMyValueType type);
如果你有不同的类型,例如字符串和双打,我会使用一种变体(如boost :: variants),而不是getValueDoubles
和getValueString
。在您的情况下,应避免使用仅按类型区分的不同吸气剂。保持您的可观察班级小而稳定。如果使用自己的返回类型,则无需重新编码整个路径,就可以使用颜色或氧气等新值扩展它。
定义一个自己的返回类型类比为observables定义一个大的基类更好,因为你可以将有关该值的几个信息放在一起,如:
temperature
source
timestamp
和
pressure
source
timestamp
扩展类型不会影响您的观察者和观察者,他们仍然是轻量级的。
最后。只有观察者应该决定他想要什么以及他是否匹配。观察员应该询问观察者并决定注册的内容和位置。观察者不应该知道观察者想要什么。直到现在我看到的任何谈判系统都失败了(在DirectShow的情况下,它失败了很多)。
答案 3 :(得分:0)
这可能是一个错误的答案,但我想知道为什么我们不能让observable返回一个变量结构(或指向它们的指针),无效字段设置为NaN(或Null
指针)或一些其他标识符。
我可以看到的一个问题是,无论观察者要求什么,它都会强制观察者提供一切。
然后怎么样:
在get()
对observable的调用中,它返回一个指向数据getter的函数指针结构。如果observable可以提供该数据,则getter不是Null
。然后观察者可以选择一个getter,检查它是否为null,然后finall获取它想要的数据。