2009-03-05 4 views
4

Я пытался следовать принципам Dependency Injection, но after reading this article, I know I'm doing something wrong.Dependency Injection и создание объекта выполнения

Вот моя ситуация: Мое приложение получает различные виды физической почты. Вся входящая почта проходит через мой объект MailFunnel.

Пока он работает, MailFunnel получает различные виды сообщений извне: Box, Postcard and Magazine.

Каждый тип почты должен обрабатываться по-разному. Например, если появляется Box, мне может потребоваться записать вес до его доставки. Следовательно, у меня есть BoxHandler, PostcardHandler и MagazineHandler объектов.

Каждый раз, когда новое сообщение приходит в мой MailFunnel, я создаю новый соответствующий MailHandler объект.

Например:

 
class MailFunnel 
{ 
    void NewMailArrived(Mail mail) 
    { 
    switch (mail.type) 
    { 
     case BOX: 
     BoxHandler * bob = new BoxHandler(shreddingPolicy, maxWeightPolicy); 
     bob->get_to_work(); 
     break; 

     case POSTCARD: 
     PostcardHandler * frank = new PostcardHandler(coolPicturePolicy); 
     frank->get_to_work(); 
     break; 

     case MAGAZINE: 
     MagazineHandler * nancy = new MagazineHandler(censorPolicy); 
     nancy->get_to_work(); 
     break; 
    } 
    } 

    private: 
    MaxWeightPolcy & maxWeightPolicy; 
    ShreddingPolicy & shreddingPolicy; 
    CoolPicturePolicy & coolPicturePolicy; 
    CensorPolicy & censorPolicy; 
} 

С одной стороны, это здорово, потому что это означает, что, если я получаю пять различных почтовых отправлений, я сразу пять различных MailHandlers работают одновременно, чтобы заботиться о бизнесе. Однако это также означает, что I'm mixing object creation with application logic - большой нет-нет, когда дело доходит до инъекции зависимостей.

Кроме того, у меня есть все эти ссылки на политику, которые висят вокруг моего объекта MailFunnel, что MailFunnel действительно не нужно. Единственная причина, по которой MailFunnel имеет эти объекты, - передать их в конструкторы MailHandler. Опять же, this is another thing I want to avoid.

Все рекомендации приветствуются. Благодаря!

ответ

8

Это больше похоже на фабрику для меня. Переместите вызов метода get_to_work() из вызова и верните обработчик. Модель работает очень хорошо для завода.

class MailHandlerFactory 
{ 
    IMailHandler* GetHandler(Mail mail) 
    { 
    switch (mail.type) 
    { 
     case BOX: 
     return new BoxHandler(shreddingPolicy, maxWeightPolicy); 
     break; 

     case POSTCARD: 
     return new PostcardHandler(coolPicturePolicy); 
     break; 

     case MAGAZINE: 
     return new MagazineHandler(censorPolicy); 
     break; 
    } 
    } 

    private: 
    MaxWeightPolcy & maxWeightPolicy; 
    ShreddingPolicy & shreddingPolicy; 
    CoolPicturePolicy & coolPicturePolicy; 
    CensorPolicy & censorPolicy; 
} 

class MailFunnel 
{ 
    MailHandlerFactory* handlerFactory; 

    MailFunnel(MailHandlerFactory* factory) { 
     handlerFactory = factory; 
    } 

    void NewMailArrived(Mail mail) { 
     IMailHandler handler = handlerFactory.GetHandler(mail); 
     handler.get_to_work(); 
    } 
} 
2

Почему у вас нет только трех методов, которые перегружены, которые берут разные типы почты, а затем делают соответствующую вещь? Или каждый тип обрабатывает сам.

Фактически, если у вас есть что-то вроде типа, скорее всего, вы должны иметь разные типы.

В принципе сделать следующее:

1) Сделать класс почты реферата.

2) Создать три подгруппы класса почты, Box, PostCard и журнал

3) Дайте каждый подкласс метода для обработки почты, или централизовать его в отдельном HandlerFactory

4) При передаче в почтовую воронку, просто попросите его вызвать метод почты дескриптора, или обработчик HandlerFactory передаст ему почту и вернет соответствующий обработчик. Опять же, вместо того, чтобы делать неудобные операторы switch везде, используйте язык, это то, для чего нужны типы и перегрузка метода.

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

Вы также можете рассмотреть использование метода шаблона, поскольку единственное реальное различие между каждым из них кажется обработчиком, которым вы являетесь, возможно, вы могли бы упростить его, так что тип почты определяет обработчик, остальная часть кода в основном то же самое.

2

Когда вы видите, что оператор switch, подумайте о полиморфизме. Эта конструкция может быть расширена только путем модификации. Я бы переделал его таким образом, чтобы добавить новое поведение, добавив классы. Это принцип открытого/закрытого.

1

Интересно, что вы применяете инъекцию зависимостей к проекту C++; это было сделано в другом месте, быстрый поиск в Google находит проект кода Google Autumn Framework.

Но ответ tvanfosson - это то, что я хотел бы предложить сначала, прежде чем принимать новую структуру.