ホームページ  >  記事  >  バックエンド開発  >  PHP 依存性注入 (DI) と制御反転 (IoC) のサンプル チュートリアル

PHP 依存性注入 (DI) と制御反転 (IoC) のサンプル チュートリアル

零下一度
零下一度オリジナル
2017-06-23 14:25:242382ブラウズ

PHP 依存性注入制御の反転の 2 つの概念を理解するには、次の 2 つの問題を理解する必要があります:

  • DI —— 依存関係の注入

  • IoC —— 制御の反転 制御の反転

依存関係注入とは何ですか

私はあなたなしでは生きていけません、つまり、あなたは私の依存関係です。 率直に言うと、

は私のものではありませんが、私が必要とするものであり、私が依存しているものです。外部から提供する必要があるものはすべて依存関係の注入が必要です。

依存性注入の例

public関数__construct(Girl $girl) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
クラス 少年 {
class Boy {
  protected $girl;
 
  public function __construct(Girl $girl) {
    $this->girl = $girl;
  }
}
 
class Girl {
  ...
}
 
$boy new Boy();  // Error; Boy must have girlfriend!
 
// 所以,必须要给他一个女朋友才行
$girl new Girl();
 
$boy new Boy($girl); // Right! So Happy! protected $girl;
$this->girl = $girl;🎜🎜 }🎜🎜}🎜🎜🎜🎜クラス 女の子{ 🎜🎜 ...🎜🎜}コード >🎜🎜 🎜🎜<code class="php 変数">$boy = 新しい Boy(); // エラー; 男の子にはガールフレンドが必要です!🎜🎜 🎜🎜 // したがって、彼にガールフレンドを与えなければなりません🎜🎜$girl = 新しい Girl();🎜🎜🎜🎜$boy = new Boy( $girl ); // そうですね!🎜🎜🎜🎜🎜🎜

上記のコードから、BoyGirl に強く依存しており、構築中に Girl のインスタンスを注入する必要があることがわかります。

Boy强依赖Girl必须在构造时注入Girl的实例才行。

那么为什么要有依赖注入这个概念,依赖注入到底解决了什么问题?

我们将上述代码修正一下我们初学时都写过的代码:

1
2
3
4
5
6
7
class Boy {
  protected $girl;
 
  public function __construct() {
    $this->girl = new Girl();
  }
}

这种方式与前面的方式有什么不同呢?

我们会发现Boy的女朋友被我们硬编码到Boy的身体里去了。。。 每次Boy重生自己想换个类型的女朋友都要把自己扒光才行。

某天Boy特别喜欢一个LoliGirl ,非常想让她做自己的女朋友。。。怎么办? 重生自己。。。扒开自己。。。把Girl扔了。。。把 LoliGirl塞进去。。。

1
2
3
4
5
6
7
8
9
10
11
12
class LoliGirl {
 
}
 
class Boy {
  protected $girl;
 
  public function __construct() {
      //  $this->girl = new Girl();  // sorry...
      $this->girl = new LoliGirl();
  }
}では、なぜ Dependency Injection という概念があるのでしょうか? Dependency Injection はどのような問題を解決するのでしょうか?
上記のコードを、初心者の頃に書いたコードに変更してみましょう:
3
4
5
1
2
6🎜7🎜🎜
クラス Boy {🎜
protected $girl;🎜
🎜 public 関数 __construct() {🎜
$this->女の子 = 新しい Girl(); 🎜
<codeclass plain>}🎜<divclass><code class="php plain">}🎜🎜🎜🎜🎜🎜🎜🎜🎜この方法と前の方法の違いは何ですか? 🎜 Boy のガールフレンドが Boy の体にハードコーディングされていることがわかります。 。 。 少年 が生まれ変わって、違うタイプのガールフレンドが欲しくなるたびに、彼は裸にならなければなりません。 🎜ある日、ボーイロリガールをとても気に入っており、彼女をガールフレンドになってもらいたいと考えています。 。 。何をするか? 自分自身を生まれ変わらせましょう。 。 。自分自身を明らかにしましょう。 。 。 女の子を捨ててください。 。 。 LoliGirl を中に入れてください。 。 。
1🎜
2🎜3🎜4🎜5🎜6🎜7🎜8🎜9🎜10🎜11🎜12🎜🎜
クラス LoliGirl {🎜
🎜}🎜<div class=" linenumber4index3alt1">🎜<divclass><codeclass>class<codeclass plain>Boy {🎜<div class="linenumber6index5alt1"> <code class="php space"> protected $girl;🎜
🎜 code><code class="php キーワード">public function __construct() {🎜
// $this->girl = new Girl(); // 申し訳ありません。 .🎜
$this->girl = 新しい LoliGirl();🎜
<codeclass plain>}🎜<div class="linenumber12index11alt1"><codeclass php plain>}🎜🎜🎜🎜🎜🎜</codeclass></div></codeclass></codeclass></div> <p>ある日、<code>ボーイ はシスター ユウに恋をしました。ボーイ はとても迷惑でした。 。 。

Boy迷恋上了御姐....Boy 好烦。。。

是不是感觉不太好?每次遇到真心相待的人却要这么的折磨自己。。。

Boy说,我要变的强大一点。我不想被改来改去的!

好吧,我们让Boy强大一点:

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
interface Girl {
  // Boy need knows that I have some abilities.
}
 
class LoliGril implement Girl {
  // I will implement Girl's abilities.
}
 
class Vixen implement Girl {
  // Vixen definitely is a girl, do not doubt it.
}
 
class Boy {
  protected $girl;
 
  public function __construct(Girl $girl) {
    $this->girl = $girl;
  }
}
 
$loliGirl new LoliGirl();
$vixen new Vixen();
 
$boy new Boy($loliGirl);気分が良くないですか?私に誠実に接してくれる人に出会うたびに、私はこうやって自分を苦しめなければなりません。 。 。
少年は言いました、私は強くなりたいです。何度も変えられたくない! 🎜それでは、Boy をもう少し強力にしてみましょう:
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🎜
インターフェース 女の子 { 🎜
// 少年は、私が何らかの能力を持っていることを知っている必要があります。🎜 }🎜<divclass>🎜<divclass>class <code class="php plain">ロリグリル実装ガール {🎜
// ガールの能力を実装していきます。🎜
}コード >🎜<div class="linenumber8index7alt1">🎜<divclass><codeclass>クラス <code class="php plain">ビクセンimplement Girl {🎜
// Vixen は間違いなく女の子です、そうしてください間違いありません。🎜
}🎜<divclass>🎜<divclass index12 alt2><code class="php キーワード">クラス ボーイ {🎜
protected $girl ; 🎜
🎜 <code class="php キーワード"> public function __construct(Girl $girl ) {🎜
$ this->girl = $girl;🎜<div class="linenumber18 Index17 alt1"> <code class="php space"> }🎜
}🎜
🎜
$loliGirl = 新しい LoliGirl();🎜<div class="linenumber22index21alt1"> <code class="php variable">$vixen = 新しい Vixen();🎜
🎜$boy = new 男の子 ($loliGirl);🎜
$boy new Boy($vixen);

Boy 很高兴,终于可以不用扒开自己就可以体验不同的人生了。。。So Happy!

依赖注入方式

1、构造器 注入

1
2
3
4
5
6
7
8
<?php
class Book {
private $db_conn;
public function __construct($db_conn) {
$this->db_conn = $db_conn;
  }
}

2、セッター注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2 4
25
26
27
<?php<?php
class Book {
private $db;
private $file;
function setdb($db) {
$this->db = $db;
    }
 
    function setfile($file) {
        $this->file = $file;
    }
}
 
class file {
}
 
class db {
}
 
// ...
 
class test {
    $book new Book();
クラス ブック {🎜 🎜 プライベート $db;🎜🎜 private $file;🎜🎜 🎜🎜 関数 setdb($db) {🎜🎜 $this->db = $db ;🎜🎜 }🎜🎜 🎜 🎜 関数 setfile($file) {🎜🎜 $this<code class="php plain">->file = $file; 🎜🎜 }🎜🎜}🎜🎜 🎜🎜クラス ファイル {🎜🎜}🎜🎜 🎜🎜クラス db {🎜🎜}🎜🎜 🎜🎜// ...🎜🎜 🎜🎜class test {🎜🎜 $book = new Book();🎜
    $book->setdb(new db());
    $book->setfile(new file());
}

概要:

ほとんどのアプリケーションは、ビジネス ロジックを実装するために相互に連携する 2 つ以上のクラスで構成されているため、各オブジェクトは連携するオブジェクト (つまり、そのオブジェクトが取得するオブジェクト) を取得する必要があります。と連携する) 依存オブジェクトへの参照)。この取得プロセスが単独で実装される場合、コードは高度に結合され、保守とデバッグが困難になります。

だからこそ、依存性注入の概念があるのです。依存性注入は次の問題を解決します:

  • 依存関係間の分離

  • Mock に便利な単体テスト

上記 2 つのメソッドのコードは非常に複雑です。しかし、多くの依存関係を挿入する必要がある場合、多くの行を追加することになり、管理が難しくなります。

より良い解決策は、すべての依存関係のコンテナーとしてクラスを作成することです。このクラスでは、必要な依存関係を保存、作成、取得、検索できます。まずはIOC

制御の反転(IOC)の概念を理解しましょう

制御の反転は、コンピュータコード間の結合を減らすために使用できるオブジェクト指向プログラミングの設計原則です。最も一般的な方法は Dependency Injection (DI) と呼ばれ、もう 1 つは「Dependency Lookup」と呼ばれます。制御の反転により、オブジェクトが作成されると、システム内のすべてのオブジェクトを制御する外部エンティティが、依存するオブジェクトの参照をそれに渡します。依存関係がオブジェクトに注入されるとも言えます。

protected$db_conn;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
<?php
class Ioc {
protected $db_conn;
public static function make_book() {
$new_book = new Book();
$new_book->set_db(self::$db_conn);
        //...
        //...
        //其他的依赖注入
        return $new_book;
    }
}
クラス Ioc {
🎜🎜 public static 関数 make_book() {🎜🎜 コード> コード><code class="php 変数">$new_book = new Book();🎜🎜 $new_book->set_db(self::$db_conn);🎜🎜 //...🎜🎜 //...🎜🎜 //その他の依存関係の注入🎜🎜 return $new_book; code >🎜🎜<code class="php space"> }🎜🎜}🎜🎜🎜 🎜🎜🎜

現時点でブックインスタンスを取得したい場合は $newone = Ioc::makebook(); を実行するだけです

上記はコンテナの特定のインスタンスです。特定のインスタンスを記述しないのが最善です。依存関係注入方法は、レジストリに登録して取得するのが良いです

11
1213
14
15
16
17
18
19
20。
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
& lt;?php
/**
* 制御反转类
コード>*/
クラス Ioc {
/**
* @var 配列に登録された依存関係配列
*/
protected static $registry = 配列 code><code class="php plain">();
/**
*レジストリ配列に解決 (匿名関数) を追加します
*
* @param string $name 依存関係識別子<?php
/**
* 控制反转类
*/
class Ioc {
/**
* @var array 注册的依赖数组
*/
protected static $registry = array();
/**
* 添加一个 resolve (匿名函数)到 registry 数组中
*
* @param string $name 依赖标识
* @param Closure $resolve 一个匿名函数,用来创建实例
* @param Closure $resolve インスタンスの作成に使用される匿名関数🎜
* @return void
*/
public static function register($name, Closure $resolve) {
static::$registry[$name] = $resolve;
}
/**
* 返回一个实例
*
* @param string $name 依赖的标识
* @return mixed
* @throws Exception
*/
public static function resolve($name) {
if (static::registered($name)) {
$name = static::$registry[$name];
return $name();
}
throw new Exception("Nothing registered with that name");
}
/**
* 查询某个依赖实例是否存在
*
* @param string $name
* @return bool
*/
public static function registered($name) {
return array_key_exists($name, static::$registry);
}
}

现在就可以通过如下方式来注册和注入一个

1
2
3
4
5
6
7
8
9
10
11
<?php
Ioc::register("book", function () {
$book = new Book();
$book->setdb('db');
    $book->setfile('file');
 
    return $book;
});
 
// 注入依赖
$book = Ioc::resolve('book');

質問の概要

1. 参加者は誰ですか?

答え: 通常、3 つの関係者が関係し、1 つはオブジェクト、もう 1 つはオブジェクトの外部リソースです。名詞についてもう一度説明します。オブジェクトは通常の Java オブジェクトを指します。IoC/DI コンテナは、単に IoC/DI 機能を実装するために使用されるフレームワーク プログラムを指します。オブジェクトの外部リソースは必要ですが、取得されます。オブジェクトの外部からのリソースは、オブジェクトが必要とする他のオブジェクトや、オブジェクトが必要とするファイル リソースなど、総称してリソースと呼ばれます。

2. 依存: 誰が誰に依存しているか?なぜ依存関係があるのでしょうか?

答え: オブジェクトは IoC/DI コンテナに依存します。プロジェクトでは、さまざまなクラス間にさまざまな関係があり、すべてが完全に独立していることは不可能であり、依存関係が形成されます。従来の開発では、他のクラスを使用するときに直接呼び出しますが、これは強い結合を形成するため、避けるべきです。依存関係の注入では、コンテナーを借用して依存オブジェクトを転送し、分離を実現します。

3. 注射: 誰が誰に注射するのか?いったい何が注入されるのでしょうか?

答え: 必要な外部リソースをコンテナを通じてオブジェクトに注入します

4. 制御の反転: 誰が誰を制御するか?何を制御しますか?なぜ逆転と呼ばれるのでしょうか?

答え: IoC/DIコンテナコントロールオブジェクトは主にオブジェクトインスタンスの作成を制御します。反転は正の方向と相対的なものですが、何が正の方向とみなされるのでしょうか?通常の状況でアプリケーションを考えてみましょう。A の中で C を使用したい場合はどうしますか?もちろん、C のオブジェクトは直接作成されます。つまり、必要な外部リソース C がクラス A で能動的に取得されます。この状況を順方向と呼びます。では、逆とは何でしょうか?つまり、クラス A は積極的に C を取得するのではなく、IoC/DI コンテナが C のインスタンスを取得するのを受動的に待ち、それを逆にクラス A に注入します。

5. 依存関係の注入と制御の反転は同じ概念ですか?

答え: 上記からわかるように、依存関係の注入はアプリケーションの観点から完全に説明できます。アプリケーションは、必要な外部リソースの作成と注入、および反転をコンテナに依存します。コンテナの観点から説明は完了です。コンテナはアプリケーションを制御し、コンテナはアプリケーションに必要な外部リソースをアプリケーションに逆に注入します。

以上がPHP 依存性注入 (DI) と制御反転 (IoC) のサンプル チュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。