如何从不同派生 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>;
我有多个派生自基本处理程序 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>;