lundi 29 mars 2021

Bridge pattern: how to define functions that call the implementation of the derived class

I am working on a polymer simulation code that employs the Bridge pattern to separate abstractions (the objects involved in the simulation) and their implementations (how they are represented e.g. one particle per monomer, continuous grid, etc.). A problem that I am facing is that I am struggling to define a class hierarchy of abstractions where lower abstractions can execute functions defined on other classes higher up in the hierarchy.

I would like to define a base abstraction Monomer that incorporates a number of methods that call the MonomerImpl implementation. Say, a method applyDisplacement to move the monomer in space. However, when I define a derived abstraction MonomerTypeA with several implementations MonomerTypeAImplGrid, MonomerTypeAImplParticles, etc., I would like to call applyDisplacement, defined at the top of the hierarchy class, but using the specific implementation of my monomer class.

This is an example of what I have tried:

class Monomer
{
  public:
    ...
    void applyDisplacement(Vector displacement)
    {
       getImplementation()->applyDisplacement(displacement);
    }

  private:
    std::unique_ptr<MonomerImpl> p_impl;
    virtual MonomerImpl* getImplementation();

};

class MonomerImpl
{
  public:
    ...
    void applyDisplacement(Vector displacement)
    {
       for (int i=0; i<positions.size(); i++)
       {
           positions[i] += displacement;
       }
    }

  private:
    std::vector<Vector> positions;

};

And:

class MonomerTypeA
{
  public:
    ...

  private:
    std::unique_ptr<MonomerTypeAImpl> p_impl;
    MonomerImpl* getImplementation()
    {
        return (MonomerImpl*) p_impl.get();
    }

};

If I use a virtual function getImplementation function can only return a MonomerImpl* pointer, then I can't implement any additional functionality to the implementation. Alternatively, if I try to scrap inheritance and just define a bunch of different implementations, I will have a lot of code duplication.

Is there any solution that gets the best of both worlds?

Aucun commentaire:

Enregistrer un commentaire