如何在不破坏其父接口的情况下向其添加属性?

时间:2019-05-17 13:29:09

标签: c++ qt

我和我正在研究的代码库用于引导物理设备(分光光度计)。它们都很相似,但是有些可以做其他人不能做的事情,并且都有自己的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,并且只会重新编译该设备。

此方法是否有警告?您是否找到解决此问题的更好方法?

0 个答案:

没有答案