多个子类层次结构

时间:2015-06-26 14:05:35

标签: c++ oop subclassing

我有类层次结构:

class AbstractProcess
{
    virtual void Do() = 0;
};

class BuildProcess : public AbstractProcess
{
    virtual void Do();
};

class UpdateProcess : public AbstractProcess
{
    virtual void Do();
};

但是,我现在想引入2(4?)个新的子类作为一个过程,也可以手动或自动化。以下看起来太长了:

class ManualBuildProcess : public BuildProcess
{
    virtual void Do();
};

class ManualUpdateProcess : public UpdateProcess
{
    virtual void Do();
};

class AutomatedBuildProcess : public BuildProcess
{
    virtual void Do();
};

class AutomatedUpdateProcess : public UpdateProcess
{
    virtual void Do();
};

如果我想引入Build / Update或Manual / Automated进程的其他子类,情况会变得更糟。

有更好的设计吗?

4 个答案:

答案 0 :(得分:1)

我可以建议两种方法。

一个是让你的Manual...Process模板化:

template<class Process> class ManualProcess: public Process {
    virtual void Do() {
        ...
        // you can access base class data:
        Process::Do();
    }
};

// use like
ManualProcess<BuildProcess> process; // instead of ManualBuildProcess

其次,有两个层次结构,更喜欢组合而不是继承,比如

class Operator;
class ManualOperator: public Operator...
class AutomaticOperator: public Operator...

class Process {
    Operator* operator;
    ...
};
class BuildProcess: public Process...
class UpdateProcess: public Process...
...

反之亦然(Operator持有指向Process的指针),甚至以OperatorProcess对称的方式彼此不了解,但第三类持有指向Operator的指针和指向Process的指针。

当然,这只适用于所有Manual个案例共有的代码和所有Build个案例共有的代码等等。如果每个版本都有自己的代码,那么你显然别无选择。

答案 1 :(得分:0)

C ++允许多重继承。这可能会使课程层次结构变得更好,但是由于这种背景很少,很难说什么是最好的。

但您可以考虑将AutomatedProcess和ManualProcess直接作为AbstractProccess的子类,就像Build Process和UpdateProcess一样。

但是,如果确实存在所有组合,那么你必须为每一个组合创建一个类,仍然会产生你现在拥有的课程数量。

您可能想要考虑自动/手动过程的作用。 它可能不需要是一个单独的类,但它可以是一个类的成员。

答案 2 :(得分:0)

我会尽量减少这里的继承并使用组合。 Manual / Automated是一个平面,Build / Update是另一个平面。似乎在两个平面中定义了Process需求策略。这可以这样做:

struct Executor;
struct Operator;

template <typename ExecutorT, typename OperatorT>
struct Process
{
    std::unique_ptr<Executor> executor_;
    std::unique_ptr<Operator> operator_;

    Process():
        executor_(new ExecutorT()),
        operator_(new OperatorT())
    {}

    void Do()
    {
        executor_->Do();
        operator_->Do();
        // do something else
    }
};

其余的非常简单,现在您可以专注于您的业务逻辑:

struct Executor
{
    virtual void Do() = 0;
};

struct Manual : Executor
{
    virtual void Do() override {}
};

struct Automated : Executor
{
    virtual void Do() override {}
};

struct Operator
{
    virtual void Do() = 0;
};

struct Build : Operator
{
    virtual void Do() override {}
};

struct Update : Operator
{
    virtual void Do() override {}
};

答案 3 :(得分:0)

除了各种面向对象的方法,例如strategy pattern,你可以在C ++中使用模板:

template <typename Action> class Process {
    Action a;
    public:
        Process(const Action& action): a{action} {};
        void do() { a.do(); };
};

template <typename Interface> class BuildAction {
    Interface i;
    public:
        BuildAction(const Interface& interface): i{intreface} {};
        BuildAction(const BuildAction& other): i{other.i} {};
        void do() { i.build(); };
};

template <typename Interface> class UpdateAction {
    Interface i;
    public:
        UpdateAction(const Interface& interface): i{intreface} {};
        UpdateAction(const UpdateAction& other): i{other.i} {};
        void do() { i.update(); };
};

class ManualInterface {
    public:
        void build();
        void update();
};

class AutomaticInterface {
    public:
        void build();
        void update();
};

typedef Process<BuildAction<ManualInterface>>     ManualBuildProcess;
typedef Process<BuildAction<AutomaticInterface>>  AutomaticBuildProcess;
typedef Process<UpdateAction<ManualInterface>>    ManualUpdateProcess;
typedef Process<UpdateAction<AutomaticInterface>> AutomaticUpdateProcess;

我可能对您的实际Usecase有一些不理想的假设。您可能会找到更好的结构,例如:

typedef Process<BuildAction, ManualInterface> ManualBuildProcess;

当然,您也可以将模板与OO模式结合起来:

Process<ManualInterface> myManualBuildProcess{BuildStrategy{}};

顺便说一句:我使用过C ++ 11语法。如果您只有C ++ 98,则必须相应地调整代码。