tags:

views:

34

answers:

2

I have an inheritance hierarchy similar to below and I want to write my DAL to persist these objects but am unsure as to the best way of structuring it?

  • Pet <- Dog <- Alsation and Labrador
  • Pet <- Cat <- Persian and Tabby

Although all classes inherit from Pet, each method will need to call a different stored procedure and add different sql parameters. There will be some common parameters though.

A few ideas:

(1) PetDal with overloaded save method that takes in each derived type.

(2) PetDal with separate SaveLabrador, SaveTabby methods.

(3) Base PetDal plus inherited LabradorDal, TabbyDal classes, one per dervied type with a common interface. eg void Save(Pet pet) which would need to cast the pet to the derived type within each method (strategy method).

(4) Some other way.

A: 

Have you thought about using a pattern like the strategy pattern? It might fit your needs as you can have different strategies for different implementations, whilst still using properties/methods from the abstract class?

Nina
From what I can tell, option (3) is basically the strategy pattern (I think). The main difference from the example on DoFactory is that the types are different here, so the algorithm defined in the strategy class (ie the save method) has to be defined with the base class and then each concrete strategy needs to cast to the appropriate dervied type.
Stacey Moore
A: 

(1) and (2) are really the same, just syntactically different. One problem with (4) is that if you want to deal with different persistent types (flat files, databases etc) then you will have to have a class for each permutation (AlsationToFileDAL, AlsationToSybaseDAL, etc).

You could use (1)/(2) with double dispatch, e.g.:

// pets.h

#include <string>
#include <iostream>

class Alsation;
class Persian;

class PetDAL
{
public:
    virtual ~PetDAL () {}

    virtual void save (const Alsation* alsation) = 0;
    virtual void save (const Persian* persian) = 0;
};

class Pet
{
    std::string name_;

public:
    Pet (const std::string& name) : name_ (name)
    {}

    virtual ~Pet () {}

    std::string getName () const
    {
        return name_;
    }

    virtual void save (PetDAL* dal) const = 0;
};

class Dog : public Pet
{
    bool sleepWalks_;
public:
    Dog (const std::string& name, bool sleepWalks) : Pet (name), sleepWalks_ (sleepWalks)
    {}

    bool getSleepWalks () const {return sleepWalks_;}

};

class Alsation : public Dog
{
public:
    Alsation (const std::string& name, bool sleepWalks) : Dog (name, sleepWalks)
    {}

    virtual void save (PetDAL* dal) const
    {
        dal->save (this);
    }
};

class Cat : public Pet
{
    int purrsPerMinute_;

public:
    Cat (const std::string& name, int purrsPerMinute) : Pet (name), purrsPerMinute_ (purrsPerMinute)
    {}

    int getPurrsPerMinute () const {return purrsPerMinute_;}
};

class Persian : public Cat
{
public:
    Persian (const std::string& name, int purrsPerMinute) : Cat (name, purrsPerMinute)
    {}

    virtual void save (PetDAL* dal) const
    {
        dal->save (this);
    }
};

class PetDALCoutImpl : public PetDAL
{
public:
    virtual void save (const Alsation* alsation)
    {
        std::cout << "Saving alsation " << std::endl
            << "\tname=" << alsation->getName () << std::endl
            << "\tsleepwalks=" << alsation->getSleepWalks () << std::endl;
    }

    virtual void save (const Persian* persian)
    {
        std::cout << "Saving persian " << std::endl
            << "\tname=" << persian->getName () << std::endl
            << "\tpurrsPerMinute=" << persian->getPurrsPerMinute () << std::endl;
    }
};

int test (int argc, char* argv[])
{
    Dog* dog = new Alsation ("fido", true);
    Cat* cat = new Persian ("dave", 10);

    PetDAL* petDAL = new PetDALCoutImpl ();

    dog->save (petDAL);
    cat->save (petDAL);

    delete cat;
    delete dog;

    return 0;
};

I.e. the Pet base class knows it's subclasses can be saved to a DAL, but it has no dependency on the DAL implementations.

jon hanson
very comprehensive. thanks.
Stacey Moore