用于处理不同继承变量集的设计模式?

Design pattern for handling different sets of inherited variables?

提问人:Askr Askr 提问时间:8/5/2023 最后编辑:Jörg BrüggmannAskr Askr 更新时间:8/7/2023 访问量:65

问:

我有一个基类,用于存储数据库记录的所有列。我想要三个子类,它们使用 Run() 方法将该记录的不同字段发送到不同的接收者。

但是,问题在于子类继承了未使用的变量(在本例中为数据库记录的字段)。

我只想在基类中使用公共字段,并将其他字段存储在子类中。

那么如何使用基类指针设置子类的成员变量呢?

没有一个类 , , 使用所有字段 (, , ...)。如果将每个子类想要的字段转移到自己的类中,那么我将如何使用父类的 SetFields 在不同的子类中设置不同的字段?Child1Child2Child3field1field2

class Interface
{
public:
    int field1, field2, field3, ..., fieldN;
    void SetFields(field1,field2,field3,fieldN); // --\> gets all the fields as arguments
    virtual void Run() = 0;
};

class Child1 : public Interface
{
public:
    void Run() {
    /// send field1, field2, field3 to recepient1
    }
};

class Child2: public Interface
{
public:
    void Run() {
    /// send field4, field5, field6 to recepient2
    }
};

class Child3: public Interface
{
public:
    void Run() {
    /// send field7, field8, fieldN to recepient3
    }
};

我需要一种可以使用父类发送子成员的设计模式。

C++ 继承设计 模式 多态性虚 函数

评论

1赞 Ted Lyngmo 8/5/2023
你也想过做吗?SetFieldsvirtual
1赞 πάντα ῥεῖ 8/5/2023
纯(纯虚拟)接口不应包含数据成员。抽象类可以使用 Mixin 模式来支持这些实现。也看看关于后者的 CRTP。最后,查看 LOKI 库中的实现示例。
1赞 Pepijn Kramer 8/5/2023
继承不是针对变量的,继承与类行为有关:参见 Liskov 的替换原理。然而,你可以做的是用一个纯虚拟公共 getter 函数列表来制作一个接口类,这实际上很常见(在单元测试中非常有用)。此接口不会具有位于另一个接口上的 Run() 方法
1赞 Some programmer dude 8/5/2023
请尝试缩进您的代码以使其更具可读性。你的老师、书籍或教程应该提到它。

答:

1赞 Jörg Brüggmann 8/6/2023 #1

要求

我只想在基类中使用公共字段,并存储 其他在子班。

  1. 类必须存储公共字段。-> 建议的类名而不是CommonInterface

Child1、Child2、Child3 类均不使用所有字段 (field1、 字段 2,...)。

  1. 其他类存储不常见的字段。-> 建议的类名而不是Additional<n>Child<n>

我想要三个子类来发送不同的字段 使用 Run() 方法记录到不同的接收者。

  1. 附加类 () 发送专用字段。Additional<n>

设计

如果我正确地理解了这些要求,那么我认为不需要继承、接口类、基类等。

我建议改用聚合。

C++ 代码

class Common
{
public:
    int mnField1;
    int mnField2;
    ...
    AdditionalA madditionalA;
    AdditionalB madditionalB;
    ...
    void SetFields(int nFieldC1, int nFieldC2, int nFieldA1, int nFieldB1) {
        mnField1 = nFieldC1;
        mnField2 = nFieldC2;
        ...
        madditionalA.mnField1 = nFieldA1;
        madditionalB.mnField1 = nFieldB1;
        ...
    }
    void Run() {
        // send mnField1, mnField2 ...
        madditionalA.Run();
        madditionalB.Run();
    }
};

class AdditionalA
{
public:
    int mnField1;
    ...
    void Run() {
        // send mnField1
    }
};

class AdditionalB
{
public:
    int mnField1;
    ...
    void Run() {
        // send mnField1
    }
};

...

提示

  • “包含” -> 聚合
    • 例如,记录包含字段。
  • “是” -> 派生
    • 例如,账单一份文件。
  • “相关” ->协会
    • 例如,客户地址项目。