c++ - 在没有额外代码的情况下链接两个独立类的最通用方法是什么?

标签 c++ qt design-patterns architecture

类的层次结构描述了某个对象的不同属性。抽象类 Property 是一个基类,它有子类:IntegerPropertyBooleanProperty 等。所有数据都在 QString 中编码,派生类以自己的方式对其进行解码。

class Property : public QObject
{
    Q_OBJECT

public:
    // ...
    virtual QString value() const = 0;
    virtual bool setValue(const QString &value) = 0;
    virtual bool validateValue(const QString& value) = 0;
    // ...
};

class IntegerProperty : public Property
{
    // ...
    virtual QString value() const override;
    virtual bool setValue(const QString &value) override;
    virtual bool validateValue(const QString& value) override;
    // ...
};

// ...

每个属性类都必须有一个独立的编辑器(GUI 小部件)- PropertyEditor(又是抽象类)、IntegerPropertyEditorBooleanPropertyEditor 等等在。

class PropertyEditor : public QWidget
{
    Q_OBJECT

public:
    inline Facer::PropertyPointer attachedProperty() { return m_property; }

protected:
    PropertyEditor(Facer::PropertyPointer attachedProperty, QWidget* parent = nullptr);

    virtual void mousePressEvent(QMouseEvent* event) override;
    virtual bool eventFilter(QObject *watched, QEvent *event) override;

    // ...
};

class IntegerPropertyEditor : public PropertyEditor
{
   // ...
};

// ...

例如,我有一组不同的属性。我不知道我到底有哪些属性,因为它们都是指向 Property 类的指针。我的任务是为这些属性创建指定的编辑器,因此如果属性对象是 IntegerProperty,我需要获取 IntegerPropertyEditor

for (Property* property : propertySet())
    PropertyEditor* editor = createEditor(property);

我用宏做了一个临时的解决方法:

#define IF_TYPE_GET_EDITOR(propertyType, editorType) \
    if (std::dynamic_pointer_cast<propertyType>(property)) \
        return new editorType(property, this);

// ...

PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
    IF_TYPE_GET_EDITOR(BooleanProperty, BooleanPropertyEditor)
    else IF_TYPE_GET_EDITOR(ColorProperty, ColorPropertyEditor)
    else IF_TYPE_GET_EDITOR(FloatingPointProperty, FloatingPointPropertyEditor)
    else IF_TYPE_GET_EDITOR(FontProperty, FontPropertyEditor)
    else IF_TYPE_GET_EDITOR(IntegerProperty, IntegerPropertyEditor)
    else IF_TYPE_GET_EDITOR(TextProperty, TextPropertyEditor)
    else throw std::runtime_error("This PropertyType is not implemented yet");
}

这看起来不是一个好的解决方案 - 如果我添加一种新类型的属性及其编辑器,我也必须更新此代码。链接编辑器类和属性类的最方便和通用的方法是什么?

最佳答案

这可能会提供一些额外的代码,特别是取决于您的项目是如何设置的,但一种解决方案是在 Property 中创建一个返回指向编辑器指针的虚函数:

class Property : public QObject
{
public:
    virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
        // let's put our default behavior here
        throw std::runtime_error("This PropertyType is not implemented yet");
    }
    //...
};

现在,您让每个类负责提供自己的编辑器:

class IntegerProperty : public Property
{
public:
    // doesn't have to be virtual, I don't think Just a regular version should be fine too.
    virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
        return new  IntegerPropertyEditor(this, widget);
    }
    //...
};

根据您拥有的类(class)数量,可能需要进行大量复制和粘贴操作。

然而,有趣的部分是 PropertySetWidget::create():

PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
    return property->CreateEditor(this);
}

因为 property 的每个 child 都负责提供自己的编辑器,所以我们不必在这个级别上担心它。如果不存在/未实现,property::CreateEditor() 将为您抛出错误。如果确实存在/已实现,它将自动向编辑器返回一个指向新实例的指针。

最大的好处是,如果你添加一个新的属性和它的编辑器,你根本不必去触及它这个功能。虚函数负责为您正确实现它。如果新属性有一个编辑器,它只需要重载那个函数,这个 create() 仍然可以正常工作。

当然,您将不得不以这种方式修改Property 的接口(interface),这在您的情况下可能不可行。这是这种方法的主要缺点。

关于c++ - 在没有额外代码的情况下链接两个独立类的最通用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57386576/

相关文章:

c++ - 类模板名称中隐藏的 friend 与内联命名空间中的另一个符号冲突

qt - 绑定(bind)到导入的 Javascript 属性

java - 使用不同的实现调用相同的方法签名

c++ - 为什么 float 非类型模板参数在 C++ 中是非法的?没有 float const experision 吗?

python - 如何调试我使用 ctypes 从 Python 调用的 Visual Studio 中的 DLL?

c++ - istringstream 十进制整数输入为8位类型

c++ - 创建 Linux GUI 元素我需要知道什么

qt - Qt 的 moc 预处理器是否需要所有 C++ 预处理器标志

ios - 修改UITableViewCell,这段代码放在哪里?对设计模式感到困惑

java - 参数化策略模式