构造方法以处理派生类型的最佳方法

时间:2010-02-24 09:16:59

标签: oop

我有一个类似于下面的继承层次结构,我想编写我的DAL来保存这些对象,但我不确定构造它的最佳方法吗?

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

虽然所有类都继承自Pet,但每个方法都需要调用不同的存储过程并添加不同的sql参数。但是会有一些共同的参数。

一些想法:

(1)具有重载保存方法的PetDal,它接收每个派生类型。

(2)PetDal具有单独的SaveLabrador,SaveTabby方法。

(3)Base PetDal加上继承的LabradorDal,TabbyDal类,每个类型有一个共同的接口。例如void Save(宠物宠物)需要在每种方法中将宠物施放到派生类型(策略方法)。

(4)其他方式。

2 个答案:

答案 0 :(得分:0)

您是否考虑过使用像strategy pattern这样的模式?它可能符合您的需求,因为您可以为不同的实现设置不同的策略,同时仍然使用抽象类中的属性/方法?

答案 1 :(得分:0)

(1)和(2)真的是一样的,只是语法上的不同。 (4)的一个问题是,如果你想处理不同的持久类型(平面文件,数据库等),那么你必须为每个排列设置一个类(AlsationToFileDAL,AlsationToSybaseDAL等)。

您可以使用(1)/(2)进行双重调度,例如:

// 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;
};

即。 Pet基类知道它的子类可以保存到DAL,但它不依赖于DAL实现。