如何从不同派生 class 的组合中添加功能?

How to add functionality from combination of different derived class?

我有多个派生自基本处理程序 class 的处理程序,它们可以单独进行单个数据更新。

例如

class Handler {
public: 
  Data_t dbdata_; 
public:
  virtual void updateFlags() = 0; 
}

class AHandler: public Handler {
.....
public:
  void updateFlags() { dbdata_.flagA = 1; }
}

class BHandler: public Handler {
.....
public:
  void updateFlags() { dbdata_.flagB = 1; }
}

class CHandler: public Handler {
.....
public:
  void updateFlags() { dbdata_.flagC = 1; }
}

根据请求中的输入标志调用各个处理程序。如果请求包含多个标志,那么在这种情况下,我想尽量避免单独创建额外的 6 个处理程序,如下所示。

class ACHandler: public Handler {
.....
public:
  void updateFlags() { dbdata_.flagA = 1; dbdata_.flagC = 1; }
}

class ABCHandler: public Handler {
.....
public:
  void updateFlags() { dbdata_.flagA = 1; dbdata_.flagB = 1; dbdata_.flagC = 1 }
}

主要功能代码将与此类似。

void process(Request_t *request)
{
  Handler *handler;
  if (request->flagA)
    handler = new AHandler();
  else if (request->flagB)
    handler = new BHandler();
  ....
  ...
  handler->updateFlags();
}

是否有更好的方法来解决这个问题,即重写处理程序如何相互连接?

提前致谢。

如果这就是您 class 所做的全部,那么我认为您不需要任何其他 class 然后 Handler。只需让 Handler 处理所有标志即可。那样会很容易和简单。我认为你可能想得太多了。获得一个工作的简单版本,然后查看它并决定您是否需要并且可以折射它。

我不知道你的 Request_t->flag(x)Data_t->flag(x) 是什么类型。

但你就不能做到吗

dbdata_.flagA = request_t.flagA;

dbdata_.flagB = request_t.flagB;

等如果您可以将它们制成数组而不是单个变量,以便于设置。

您可能需要考虑 policy-based class 设计。为此,我们定义了一个可变函数模板 execute() 和一个 class 模板 HandlerHolder,它继承自 Handler 并覆盖 updateFlags() 成员函数:

template<typename FlagUpdater, typename... FlagUpdaters>
void execute(Data_t& data) {
    execute<FlagUpdater>(data);
    if constexpr (sizeof...(FlagUpdaters))
        execute<FlagUpdaters...>(data);
}

template<typename... FlagUpdaters>
class HandlerHolder final: public Handler {
public:
    void updateFlags() override {
        if constexpr (sizeof...(FlagUpdaters)) 
            execute<FlagUpdaters...>(dbdata_);
    }
};

对于这个可变 class 模板 HandlerHolder,您可以将 classes(即策略)作为可调用的模板参数传递并设置适当的标志。这些策略 classes 的函数调用运算符(即 operator())在其覆盖的成员函数 updateFlags().

中被调用

然后您可以像这样定义策略 class:

struct AFlagSetter {
    void operator()(Data_t& dbdata) const {
        dbdata.flagA = 1;
    }
};

struct BFlagSetter {
    void operator()(Data_t& dbdata) const {
        dbdata.flagB = 1;
    }
};

struct CFlagSetter {
    void operator()(Data_t& dbdata) const {
        dbdata.flagC = 1;
    }
};

请注意,您还可以轻松定义清除标志的策略,例如:

struct CFlagClearer {
    void operator()(Data_t& dbdata) const {
        dbdata.flagC = 0;
    }
};

通过类型别名,您可以为您正在寻找的处理程序引入类型名称:

using ACHandler = HandlerHolder<AFlagSetter, BFlagSetter>;
using ABCHandler = HandlerHolder<AFlagSetter, BFlagSetter, CFlagSetter>;