Best Construct for Db Abstraction with Inheritance

My application processes different messages and stores them in the database. Right now I have used the following design:

Database class:

class DbObject
{
public:
    // read/write object members from/to DB 
    virtual void readFromDb() = 0;
    virtual void writeToDb() = 0;

    // Other stuff, db connection etc.
    void doDbStuff();
}

      

Base class for messages:

class BaseMsg
{
public:
    // read/write object members from/to DB 
    virtual std::string toXml() = 0;
    virtual void fromXml(const & std::string s) = 0;
}

      

Message types A, B, etc.

class MsgA : public BaseMsg, DbObject
{
public:
    std::string toXml();
    void fromXml(const & std::string s);

    void readFromDb();
    void writeToDb();
}

      

This project works well, each processed message gets its own object, can be written to XML, read from XML, saved and read to / from a database with specific messages (implemented in MsgA).

However, we are currently considering porting the application to a new platform where the current database is not available, so we will use an additional database type.

Typically I would have a base class for database access and child classes for each type of database. But with the current design it is not possible, because I don't want to have an MsgADatabase1 class and an MsgADatabase2 class, etc.

Is there some design pattern where I could keep the current design in principle, but hide the currently used database type behind some level of abstraction?

+3


source to share


2 answers


1. First thought would be to see it DbOject

as an adapter.

According to the Gang of Four, adapter will offer a target interface for an adapted object (a specific database object), either through multiple inheritance or in composition.

In the context of your multiple inheritance, this design will impose that for each DbObject

that you inherit in a message, its constructor will create a single reference to a specific DB project. But how can a constructor know which specific db class to create?

2.Next thought: combine this adapter with an abstract factory

The most natural pattern for creating a concrete database dependent object that instantiates an abstract database independent would be using the abstract factory tag .

Combined with an adapter, you would have the following scenario:

  • on startup, the virtual factory object (class Database

    ) gets an instance with a specific dependent database factory ( class DatabaseBrandA : public Database

    )
  • a virtual factory provides a function to create DbIndependentObject

    . A concrete factory implements this function by providing its own concrete objects ( class DbBrandAdependentObject : public DbIndependentObject

    )
  • Each time a message is generated, the underlying adapter DbObject

    requests a virtual factory to create a new object. So it is referring to DbIndependentObject

    , implemented with DbBrandAdependentObject

    )


However, I don't know if your content is really DbObject

so rich that it needs a one-to-one relationship with a specific database object. Isn't such a complex model redundant?

3. Final conclusion: adapter combined with proxy template

I suspect your DbObject

only means a convenient way to get virtual read and write functions implemented by a derived message object that can be called whenever interaction with the database is required.

If your current code is designed to DbOject

encapsulate everything related to a database, you just need a proxy to that database.

This will work according to the following scenario:

  • on startup, abstract database object (class Database

    ) gets an instance with concrete database ( class DatabaseBrandA : public Database

    )
  • Each time a message is generated, the database DbObject

    acts as a proxy that refers to the database object.
  • Each time a database operation needs to be performed, it DbObject

    acts as an adapter for the message, providing the necessary read-write functionality.
+3


source


You can implement the adapter pattern and keep the datasource (any DB or other datasource) as an external object to reduce communication.



+2


source







All Articles