mercredi 16 mai 2018

C++ Design and polymorphism

I have a generic question on C++ class design. For example I have a need for a packet generator. So given a type of packet I have to generate the packet of that type. So I have a base packet generator class.

Approach 1:

class BasePacketGenerator {
public:
    virtual Packet* generatePacket (int type); // implements the generic case
                                               // hence not pure virtual
protected:
    //
    // Common functionality for all types
    // 
   virtual void massagePacket (Packet& pkt); // called by generatePacket
                                           // but needs special handling for 
                                           // some types
   virtual void calculateCheckSum(Packet& pkt); // called by generate packet
   ...
};

Derived classes to handle each type:

class Type1PacketGenerator : public BasePacketGenerator {
public:
    // Dont have to override any base class implementationa
protected:
    void calculateCheckSum(Packet& pkt) override;
};

class Type2PacketGenerator : public BasePacketGenerator {
public:
    Packet* generatePacket(int type) override;
};

Here for Type1 generator, we are using polymorphism. But the base-class calls, the derived class functionality polymorphically. I wonder if this is a good Idiom? Or there should be a intermediator class

Approach 2:

class TypeHandler {

    virtual Packet* setupPacket();
    virtual void calculateCheckSum(Packet& pkt);
    virtual void setupFields (Packet& pkt);
}

class PacketGenerator {
public:

    TypeHandler *handler_; // lets say this is setup based on the type

    Packet* generatorPacket(int type)
    {
       auto packet = handler_->setupPacket();
       handler_->massagePacket();
       handler_->calculateCheckSum(*packet);
       return packet;
    }
}

Is there any advantage with going with one approach or the other?

Approach1 is more flexible as it doesn't have to follow the same way of doing things. Eg: if Type2Generator doesn't need a checksum, it doesn't even have to call the calculateCheckSum() or if it needs some additional functionality, we don't have to add it to all Type generators.

But Approach 2 is more readable as all types do the things same way.

Aucun commentaire:

Enregistrer un commentaire