我有类层次结构:
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进程的其他子类,情况会变得更糟。
有更好的设计吗?
答案 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
的指针),甚至以Operator
和Process
对称的方式彼此不了解,但第三类持有指向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,则必须相应地调整代码。