抽象工厂,依赖注入和良好的设计

时间:2010-11-04 23:41:55

标签: c++ dependency-injection factory-pattern

我正在努力获得良好系统设计的诀窍。由于没有严格的系统设计规则,我请你给我一些宝贵的建议。我准备了一个想象系统并为此准备了一个设计。如果你认为这个设计是好还是坏,请告诉我。有没有更好的办法?我在解决方案中使用了Abstract Factory和Dependency Injection。

问题:

设计一个在汽车中运行并控制它的系统。要求是为大众高尔夫控制部件制造系统,如发动机,电气,变速箱等。

可以有不同版本的高尔夫,如BlueMotion,Twist,GT等,它们使用不同的组件。例如,如果GT使用引擎a和电气b,BlueMotion可以使用引擎c和电气d。

不同车型中的发动机,电气和其他部件可能类似,或者可能完全不同。例如,“Flat 4 CRDI”发动机使用CRDI技术进行燃料喷射,并具有减少振动的特定行为。 “PumpeDuse V6”发动机采用PD喷射和自身减少振动的方法,与“Flat4 CRDI”完全不同。不同之处不仅在于处理振动,还在于发动机行为的大部分方面。

截至目前,系统模型应该处理Engine的启动。启动发动机意味着使用来自电气系统的动力并启动发动机并保持空转。首先,使用“Pumpe Duse E250”发动机和“BoschR10”电气系统制作高尔夫“GT”。但是,未来可以推出许多不同的系列,系统应该能够以最小的麻烦扩展功能和车型。

更新:根据建议编辑代码。

代码:

class Electrical
{
public:
    virtual void OpenCircuit() = 0;
};

class Engine
{
public:
    virtual void Crank(Electrical *) = 0;
};

class CarComponentFactory
{
public:
    virtual Engine* CreateEngine()=0;
    virtual Electrical* CreateElectrical()=0;
};

class PumpeDuseE250:public Engine
{
    virtual void Crank(Electrical *pEle)
    {
        pEle->OpenCircuit();
        //Do the crank
    }
};

class BoschR10: public Electrical
{
    virtual void OpenCircuit()
    {
        //Open the Circuit
    }
};

class GTFactory:public CarComponentFactory
{
public:
    virtual Engine* CreateEngine()
    {
        return new PumpeDuseE250();
    }

    virtual Electrical* CreateElectrical()
    {
        return new BoschR10();
    }
};

class VWGolf
{
    auto_ptr<Engine> mpEngine;
    auto_ptr<Electrical> mpElectrical;      
public:
    VWGolf(Engine *pEngine, Electrical *pElectrical):mpEngine(pEngine), mpElectrical(pElectrical)
    {
    }

    void Start()
    {
        mpEngine->Crank(mpElectrical.get());
    }

    ~VWGolf()
    {           
    }
};

创建对象的示例:

void main()
{
    GTFactory Factory;
    VWGolf golfGT(Factory.CreateEngine(), Factory.CreateElectrical());
    golfGT.Start();
}

请注意,“BoschR10”这样的名称是虚构的。

2 个答案:

答案 0 :(得分:4)

这就是我要做的事情:

从基础开始:

class Car {};

然后根据需要对其进行扩展。

到目前为止,没有进一步的要求。 没有要求汽车使用不同的组件用于任何事情,所以我暂时不让它们出去。我们必须能够创建具有特定组件的汽车。但是在我们知道这些组件应该做什么之前,没有理由让它们成为评论:

// create a car using engine A and gearbox B
Car car1;

// create one with engine C and electrical D
Car car2;

我们有。这是我的设计。鉴于这一起点,当您提出更多要求时,扩展系统所需的代码非常少。当需求发生变化时,几乎没有任何东西可以破坏或需要重写。它简单而干净。

所以现在,我得出结论,这是符合您要求的理想设计。与大的继承层次结构相比,它更强大,更有效,并且不太可能包含错误。它也是百分之百可重复使用的代码。

正如您可能从我的评论中收集的那样,好的设计取决于背景。摘要中没有“汽车”的好设计。

但我们可以为“赛车游戏”或“管理汽车工厂的系统”,或“显示汽车各种属性的状态(门打开或关闭,当前)提供良好的设计”速度,油位,松开安全带)。“

设计不依赖于您正在建模的对象,而是取决于您要对其进行的操作。从你到目前为止的描述来看,除了在那里之外,对象的目的一无所获。所以我建议一个模型,其中汽车在那里,没有别的。

最好的设计不是最能描述某些物理对象的设计,而是最能让您的应用程序完成它应该做的事情的设计。

如果您的所有应用程序都应该“有车”,那么模型就会变得非常简单。

答案 1 :(得分:3)

我将删除工厂之间的依赖关系(实际应用依赖注入)和VWGolf,我确保使用RAII而不是原始指针。你应该看起来像这样:

void main() // still not applying RAII
{
  GTFactory factory;
  VWGolf golfGT(factory.CreateEngine(), factory.CreateElectrical());
  golfGT.Start();
}

计算你需要做多少次嘲讽,以便用自己的方式测试VWGolf。