2009-03-05 2 views
4

私は依存性の注入の原則に従うことをしようとしてきたが、after reading this article, I know I'm doing something wrong.依存性注入と実行時オブジェクトの作成

は、ここに私の状況です:私のアプリケーションは、物理的なメールの種類を受け取ります。すべての受信メールは私のMailFunnelオブジェクトを通過します。

実行中、MailFunnelは外部からさまざまな種類のメッセージを受信します:ボックス、郵便はがき、雑誌。

それぞれのメールタイプを別々に処理する必要があります。たとえば、Boxが入ってくると、配送前に重量を記録する必要があるかもしれません。したがって、私はBoxHandler,PostcardHandlerMagazineHandlerオブジェクトを持っています。

新しいメッセージが私の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; 
} 

それは私がメールの五つの異なる部分を取得する場合、私はすぐに5異なる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

さまざまな種類のメールを受け取って適切な処理を行う3つの方法がありますか?または、それぞれの型がそれ自身を処理するようにします。

実際に、タイプのようなものがある場合は、実際には異なるタイプを持つ必要があります。

は、基本的には次のようにします。

1)メールクラスを抽象クラスにします。

2)メールの三つのサブクラスを作成し、ボックス、ポストカード、およびマガジン

3)各付けのメールを処理するメソッドをサブクラス、または渡された場合は、別HandlerFactory

4)でそれを集中単にメールの処理方法を呼び出させるか、HandlerFactoryにメールを渡して適切なハンドラを返すようにしてください。繰り返しますが、あらゆる場所で厄介なswitch文を使用するのではなく、言語を使用します。これが、型とメソッドのオーバーロードの目的です。

メール処理が複雑になって取り出したい場合は、最終的にメールハンドラクラスを作成し、それらのポリシーを抽出することができます。

テンプレートメソッドの使用を検討することもできます。それぞれの実際の違いは、インスタンス化したハンドラである可能性があります。メールタイプによってハンドラ、コードの残りの部分基本的に同じです。

2

switch文が表示されたら、多態性を考えてください。この設計は修正によってのみ拡張することができます。クラスを追加することで新しい振る舞いを追加できるようなやり方でやり直したいと思います。それはオープン/クローズドな原則のすべてです。

1

興味深いことに、C++プロジェクトに依存性インジェクションを適用すると面白いです。他の場所で行われているので、すばらしいGoogle検索でGoogleコードプロジェクトAutumn Frameworkが見つかりました。

しかし、tvanfossonの答えは、新しいフレームワークを採用する前にまず試してみることです。