googytech
googytech

Reputation: 479

How to add functionality from combination of different derived class?

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

Answers (2)

jfMR
jfMR

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

b23v
b23v

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

Related Questions