我和我正在研究的代码库用于引导物理设备(分光光度计)。它们都很相似,但是有些可以做其他人不能做的事情,并且都有自己的SDK和驱动程序。
我们经常必须支持新设备,每个设备都有其自己非常特定的属性。
主要设备接口(例如IDevice)具有很多纯虚拟属性,用于确定设备(例如Device1,Device2等)是否可以执行给定的操作,或它支持的操作类型。
IDevice.h
class IDevice : public QObject {
Q_OBJECT
public:
virtual ~IDevice() {}
virtual bool canDoOperationA() = 0;
virtual bool canDoOperationB() = 0;
virtual QVariant supportedMode() = 0;
// etc. There are a lot of these ‘canDo’ and ‘supported’ interfaces.
// dozens of other things, slots, signals, etc.
};
Device1.h
class Device1 : public IDevice {
public:
bool canDoOperationA() { return true; }
bool canDoOperationB() { return false; }
QVariant supportedMode() { return QStringList{{ “m1”, “m2” }}; }
};
Device2.h
class Device2 : public IDevice {
public:
bool canDoOperationA() { return false; }
bool canDoOperationB() { return true; }
QVariant supportedMode() {
return getModesAtRuntime();
}
private:
QVariant getModesAtRuntime() {
/* determine at runtime what modes are supported,
depending on the device current configuration */
return QVariant();
}
} ;
大多数这些属性在编译时就已知,但是其中某些属性(取决于设备)必须在运行时确定(通常是通过设备SDK进行,该SDK可以询问设备本身的状态)。
我们经常需要支持新的设备和/或属性,从而在IDevice中添加了其他canDoOperationXXX方法(随着时间的流逝,这些方法变得很麻烦)。例如,如果特定设备需要支持operationC和SpecialMode,则IDevice将变为:
IDevice.h
class IDevice : public QObject {
Q_OBJECT
public:
virtual ~IDevice() {}
virtual bool canDoOperationA() = 0;
virtual bool canDoOperationB() = 0;
virtual QVariant supportedMode() = 0;
virtual bool canDoOperationC() = 0;
virtual QVariant supportedSpecialMode() = 0;
};
然后需要更新和重新编译所有设备(它们甚至不知道OperationC和SpecialMode)。我认为这是设计缺陷。
我想知道是否存在一种在不破坏API的情况下在设备中添加新属性的最佳方法。
我正在考虑从IDevice删除所有canDoOperation和supportedModes方法,并用单个接口替换它们
QVariant getProperty(const QString& propertyName) = 0;
这样,设备将返回其自己的属性(运行时或编译时)。如果不支持属性,则返回无效的QVariant。将特定属性添加到特定设备不会破坏API,并且只会重新编译该设备。
此方法是否有警告?您是否找到解决此问题的更好方法?