酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

DI(Dependency Injection)の概念入門[Java]

Javaで「DI(Dependency Injection) / 依存性の注入」という概念があります。 これは簡単にいうと、「コンポーネント間の依存関係を外部の設定ファイルから設定(注入)できるようにすること」とのことです。


やりたいこと

あるクラス内の定数や変数、インスタンスを排除して、外部ファイルなどに設定したものを 受け取れるようにすることで、動的に動作を変えられるようにする。

メリット

依存性を排除することによる問題解決

  • 中に別のクラスが入っているとテストがしづらい => テストが容易になる
  • テストに時間のかかるメソッドがある => 時間のかかるテストを排除できる

設計の容易性と変化に強くなる

  • ソフトウェアの階層構造を綺麗に分離した設計が容易となる
  • 特定のフレームワークへの依存度が極小になり、変化に強いソフトウェアを作る事ができる

デメリット

  • クラスを大量に作る必要があり、初期コストがかさむ
  • プログラムの実行速度が遅くなる可能性がある

サンプルソース

Wikipedia からのコピペですが、サンプルは以下の様なソースです。

各コンポーネントのインターフェース

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IOnlineBrokerageService {
    String[] getStockSymbols();
    double getBidPrice(String stockSymbol);
    double getAskPrice(String stockSymbol);
    void putBuyOrder(String stockSymbol, int shares, double buyPrice);
    void putSellOrder(String stockSymbol, int shares, double sellPrice);
}

public interface IStockAnalysisService {
    double getEstimatedValue(String stockSymbol);
}

public interface IAutomatedStockTrader {
    void executeTrades();
}

DIを使わない場合のソース

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class VerySimpleStockTraderImpl implements IAutomatedStockTrader {

    private IStockAnalysisService analysisService = new StockAnalysisServiceImpl();
    private IOnlineBrokerageService brokerageService = new NewYorkStockExchangeBrokerageServiceImpl();

    public void executeTrades() {
        .
    }
}

public class MyApplication {
    public static void main(String[] args) {
        IAutomatedStockTrader stockTrader = new VerySimpleStockTraderImpl();
        stockTrader.executeTrades();
    }
}

DIを使ったリファクタリング

MyApplication.main()で依存度するクラスを設定している。これにより、VerySimpleStockTraderImpl 自体は特定の実装に依存をしなくなっている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class VerySimpleStockTraderImpl implements IAutomatedStockTrader {

    private IStockAnalysisService analysisService;
    private IOnlineBrokerageService brokerageService;

    public VerySimpleStockTraderImpl(
            IStockAnalysisService analysisService,
            IOnlineBrokerageService brokerageService) {
        this.analysisService = analysisService;
        this.brokerageService = brokerageService;
    }
    public void executeTrades() {
        
    }
}

public class MyApplication {
    public static void main(String[] args) {
        IStockAnalysisService analysisService = new StockAnalysisServiceImpl();
        IOnlineBrokerageService brokerageService = new NewYorkStockExchangeBrokerageServiceImpl();

        IAutomatedStockTrader stockTrader = new VerySimpleStockTraderImpl(
            analysisService,
            brokerageService);
        stockTrader.executeTrades();
    }
}

あとがき

サンプルソースがwikipediaのコピペになってしまったのは申し訳ないですが、 プログラムを書くときに参考になりそうな概念で面白かったです!


Special Thanks

おすすめの書籍