1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Dependency Injection(依存性の注入)とは

Last updated at Posted at 2020-04-21

 私は、最近PHPとLaravelに触れ始めた初心者エンジニアなのですが、
Laravelのドキュメントを読んでいたら「依存」という言葉がたくさん出てきて、
わからなかったので調べてみたら、とても理解が難しかったので、分かった点を
まとめてみました。

#Dependency Injection(DI)とは
 日本語では「依存性の注入」と訳される。
 「あるオブジェクトを、それを使用するオブジェクトに渡す」
というデザインパターンの1つ。
##DIパターンの例 ① コンストラクタ・インジェクション

// 使用する側のクラス
class Client
{
    private $service;
    // コンストラクタでServiceオブジェクトを渡している。
    public function __construct(Service $service)
    {
        $this->service = $service;
    }

    public function doSomething()
    {
        $this->service->doSomething();
    }
}

// 使用される側のクラス
class Service
{
    public function doSomething()
    {
        // 処理
    }
}

 上記のコードではコンストラクタを使ってオブジェクトを渡しているため、
「コンストラクタ・インジェクション」と呼ばれる。

 オブジェクトの渡し方によって、DIパターンの手法は以下のようなものもある。

##DIパターンの例 ② メソッド・インジェクション
  メソッドの引数にオブジェクトを渡す。

// 使用する側のクラス
class Client
{
    // メソッドでServiceオブジェクトを渡している。
    public function doSomething(Service $service)
    {
        $service->doSomething();
    }
}

// 使用される側のクラス
class Service
{
    public function doSomething()
    {
        // 処理
    }
}

##DIパターンの例 ③ セッター・インジェクション
  DI用のセッターを用意してオブジェクトを渡す。

// 使用する側のクラス
class Client
{
    private $service;
    // DI用のセッターを用意してServiceオブジェクトを渡している。
    public function setService(Service $service)
    {
        $this->service = $service;
    }

    public function doSomething()
    {
        $this->service->doSomething();
    }
}

// 使用される側のクラス
class Service
{
    public function doSomething()
    {
        // 処理
    }
}

##【DIパターンでない例】


// 使用する側のクラス
class Client
{
    private $service;

    public function __construct()
    {
        // コンストラクタ内でServiseオブジェクトを生成している。
        $this->service = new Service();
    }

    public function doSomething()
    {
        $this->service->doSomething();
    }
}

// 使用される側のクラス
class Service
{
    public function doSomething()
    {
        // 処理
    }
}

###DIパターンの特徴

  • オブジェクトの生成と仕様が分離されている
  • クライアントがサービスを呼ぶのではなく、サービスが外部からクライアントに注入される。つまり、制御が反転している。

 DIパターンでない場合、ClientオブジェクトはServiceオブジェクトがないと動作できないため、**「ClientはServiceに依存している」**ということになる。
「依存」と訳されるのはそういう事のようだ。

##抽象への依存


class Client
{
    private $service;
    // コンストラクタ
    // 実行時に、ServiceInterfaceインターフェースを実装したクラスのオブジェクトが
    // 渡されれば実行できる。
    public function __construct(ServiceInterface $service)
    {
        $this->service = $service;
    }

    public function doSomething()
    {
        $this->service->doSomething();
    }
}

// ServiceInterfaceインターフェイス
interface ServiceInterface
{
    public function doSomething();
}
// ServiceInterfaceを実装したServiceクラス
class Service implements ServiceInterface
{
    public function doSomething()
    {
        // 処理
    }
}

 上記のコードでは、ClientはServiceinterfaceインターフェイスを実装したオブジェクトがあれば動作できる。

 Serviceオブジェクトに限らず、Serviceinterfaceインターフェイスを実装したオブジェクトがあれば良いので、このような場合は**「抽象に依存している」**という。

###【疎結合】
 この場合、オブジェクトをDIで別の実装(クラス)に差し替えることができて、
ClientとServiceの**(クラス間の)結合度が緩くなる。**疎結合という。

###【密結合】
 DIパターンではないコードの場合(ClientがServiceに依存している場合)、
ClientとServiceの**(クラス間の)結合度がきつい。**密結合という。

#手動でのDI
 上記の例で、Clientクラスを使うには以下のようにする。
 DIパターンは、「あるオブジェクトを、それを使用するオブジェクトに渡す」
パターン
なので、
 使用されるオブジェクトを使用するオブジェクトの外部で生成し、使用するオブジェクトに注入することで、DIパターンを使用していると言える。
 以下のようなコードを**「手動でのDI」**という。

    // Serviceオブジェクト(使用される側)の生成
    $service = new Service();
    // Clientオブジェクト(使用する側)に注入 手動DI
    $client = new Client($service);

 DIパターンについては、こういうものがあるんだということを知れて、触りだけ
でも理解できたので良かった。

 Laravelでは、DIにまつわる部分を担当する「サービスコンテナ」を中心として
フレームワークが作られているようなので、次はサービスコンテナについて理解
したいと思う。

#参考資料 

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?