Reputation: 479
I have multiple handlers derived from base Handler class which can do single data updates individually.
For eg.
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; }
}
Individual handlers are called based on input flags in request. If request contains multiple flags, then in this case I want to try to avoid creating additional 6 handlers individually like following.
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 }
}
Main function code will be something similar to this.
void process(Request_t *request)
{
Handler *handler;
if (request->flagA)
handler = new AHandler();
else if (request->flagB)
handler = new BHandler();
....
...
handler->updateFlags();
}
Is there a better way to approach this problem, by re-writing how the handlers are connected to each other ?
Thanks in advance.
Upvotes: 2
Views: 89
Reputation: 24738
You may want to consider a policy-based class design. For this, we define both a variadic function template, execute()
, and a class template, HandlerHolder
, that inherits from Handler
and overrides the updateFlags()
member function:
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_);
}
};
To this variadic class template, HandlerHolder
, you can pass classes (i.e., policies) as template arguments that are callables and set the proper flags. The function call operator (i.e., operator()
) of these policy classes are called in its overridden member function updateFlags()
.
You would then define the policy classes like:
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;
}
};
Note that you can also easily define policies for clearing the flags, for example:
struct CFlagClearer {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 0;
}
};
By means of type aliases you can introduce type names for the handlers you were looking for:
using ACHandler = HandlerHolder<AFlagSetter, BFlagSetter>;
using ABCHandler = HandlerHolder<AFlagSetter, BFlagSetter, CFlagSetter>;
Upvotes: 1
Reputation: 86
If this is all your classes do, then I dont think u need any other class then Handler
. Just simply let the Handler
handle all the flags. It will be easy and simple like that. I think you might be overthinking this. Get a working simple version and then review it and decide if u need to and can refractor it.
I dont know what type your Request_t->flag(x)
and Data_t->flag(x)
is.
But cant you just do
dbdata_.flagA = request_t.flagA;
dbdata_.flagB = request_t.flagB;
etc. If you can maybe make them an array instead of individual variables, for easier setting.
Upvotes: 2