Абстрактная фабрика, внедрение зависимостей и хороший дизайн - PullRequest
2 голосов
/ 05 ноября 2010

Я пытаюсь получить хороший дизайн системы. Поскольку нет жестких и быстрых правил для хорошего проектирования системы, я прошу вас дать мне несколько ценных предложений. Я подготовил воображаемую систему и подготовил проект для этого. Пожалуйста, дайте мне знать, если вы думаете, хорошо это или плохо. Есть ли способ лучше? Я использовал Абстрактную Фабрику и Внедрение Зависимостей в решении.

Проблема:

Разработка системы, которая работает в автомобилях и контролирует ее. Требуется создать систему для управления такими компонентами Volkswagen Golf, как двигатель, электрика, коробка передач и т. Д.

Могут быть разные версии Golf, такие как BlueMotion, Twist, GT и т. Д., В которых используются разные компоненты. Например, если GT использует двигатель a и электрический b, BlueMotion может использовать двигатель c и электрический d.

Двигатели, электрика и другие компоненты в разных автомобилях могут быть похожими или совершенно другими. Например, «Flat 4 CRDI» Engine использует технологию CRDI для впрыска топлива и имеет определенное поведение для снижения вибрации. Двигатель «PumpeDuse V6» использует впрыск PD и собственный метод снижения вибрации, который полностью отличается от «Flat4 CRDI». Разница заключается не только в обработке вибраций, но и в большинстве аспектов поведения двигателя.

На данный момент модель системы должна обрабатывать запуск Engine. Запуск двигателя означает использование энергии от электрической системы, проворачивание двигателя и сохранение холостого хода. Для начала сделайте Golf GT с двигателем Pumpe Duse E250 и электрической системой BoschR10. Однако в будущем может быть запущено множество различных серий, и система должна иметь возможность расширять функциональность и модели автомобилей с минимальными трудностями.

Обновление: код отредактирован согласно предложениям.

Код:

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 ]

4 голосов
/ 05 ноября 2010

Вот что я бы сделал:

Начните с основ:

class Car {};

, а затем расширьте его по мере необходимости.

Дело в том, что никаких дополнительных требований пока нет. Не существует требования, чтобы автомобиль использовал различные компоненты для чего-либо, поэтому я оставлю их пока. Мы просто должны быть в состоянии создать автомобиль с определенными компонентами. Но пока мы не знаем, что эти компоненты должны делать , нет никаких причин делать из них что-то большее, чем комментарий:

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

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

И вот мы здесь. Это мой дизайн. Учитывая эту отправную точку, для расширения системы требуется совсем немного кода, когда вы предъявляете больше требований. Практически ничего не может сломаться или потребовать переписывания при изменении требований. Это просто и чисто.

Итак, на данный момент я пришел к выводу, что это идеальный дизайн, соответствующий вашим требованиям. Он гораздо надежнее, гораздо эффективнее и с меньшей вероятностью содержит ошибки, чем ваша большая иерархия наследования. И это также стопроцентный код многократного использования.

Как вы, вероятно, поняли из моих комментариев по вашему вопросу, хороший дизайн зависит от контекста. Не существует хорошего дизайна для "автомобилей" в аннотации.

Но мы можем предложить хороший дизайн для «автомобилей для гоночной игры», или «системы управления автомобильным заводом», или для «отображения состояния различных свойств автомобиля (двери открыты или закрыты, текущие) скорость, уровень топлива, отстегнуты ремни безопасности). "

Дизайн не зависит от того, какие объекты вы моделируете, а от того, что вы хотите с ними сделать . И из вашего описания до сих пор, цель объектов не что иное, как быть там. Поэтому я предлагаю модель, где машины есть и ничего больше.

Лучший дизайн - это не тот, который лучше всего описывает некоторый физический объект, а тот, который лучше всего позволяет вашему приложению делать то, что он должен делать.

И если все ваше приложение должно делать «иметь машину», то модель становится довольно простой.

3 голосов
/ 05 ноября 2010

Я бы удалил зависимость между фабриками (фактически применил внедрение зависимостей) и VWGolf, и я бы обязательно использовал RAII вместо необработанных указателей.Ваш главный должен выглядеть примерно так:

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

Подсчитайте, сколько макетов вам нужно сделать, чтобы протестировать VWGolf со своим путем против моего.

...