> 백엔드 개발 > PHP 튜토리얼 > PHP 종속성 주입(DI) 및 제어 반전(IoC) 예제 튜토리얼

PHP 종속성 주입(DI) 및 제어 반전(IoC) 예제 튜토리얼

零下一度
풀어 주다: 2023-03-10 17:22:01
원래의
2449명이 탐색했습니다.

PHP 종속성 주입제어 반전의 두 가지 개념을 이해하려면 다음 두 가지 문제를 이해해야 합니다.

  • DI —— 종속성 주입

  • IoC —— 제어 반전

의존성 주입이란 무엇입니까

당신 없이는 살 수 없습니다. 그렇다면 당신은 나의 의존성입니다. 직설적으로 말하면:

그것은 내 것이 아니지만 나에게 필요하고 의지하는 것입니다. 외부적으로 제공되어야 하는 모든 것에는 종속성 주입이 필요합니다.

종속성 주입의 예

공개함수 <code class="php plain">__construct(소녀 $girl) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class 소년 {
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! 보호됨 $girl;
$this->girl = $girl;🎜🎜 }🎜🎜}🎜🎜🎜🎜클래스 여자 { 🎜🎜 ...🎜🎜} code >🎜🎜 🎜🎜<code class="php 변수">$boy = Boy(); // 오류; 소년에게는 여자친구가 있어야 합니다!🎜🎜 🎜🎜 // 그러므로 여자친구를 주어야 합니다🎜🎜$girl = Girl();🎜🎜🎜🎜$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();
  }
}그렇다면 종속성 주입이라는 개념이 왜 있는 걸까요? 종속성 주입은 어떤 문제를 해결하나요?
위 코드를 우리가 처음에 작성했던 코드로 수정해 보겠습니다:
3
4
5
1
2
6🎜
7🎜🎜
클래스 소년 {🎜
보호됨 $girl;🎜
🎜
공개 함수 __construct() {🎜
$this->girl = new Girl(); 🎜
}🎜
}🎜🎜🎜🎜🎜🎜🎜🎜🎜이 방법과 이전 방법의 차이점은 무엇인가요? 🎜우리는 소년의 여자친구가 소년의 몸에 하드코딩되어 있음을 발견하게 됩니다. . . 소년이 다시 태어나서 다른 유형의 여자친구를 원할 때마다 그는 발가벗겨야 합니다. 🎜어느 날 소년롤리걸을 정말 좋아하고 그녀가 자신의 여자친구가 되기를 진심으로 원합니다. . . 무엇을 해야 할까요? 자신을 다시 태어나십시오. . . 자신을 발견하세요. . . 소녀를 버리세요. . . 롤리걸을 안에 넣어주세요. . .
1🎜
2🎜
3🎜
4🎜
5🎜
6🎜
7🎜
8🎜
9🎜
10🎜
11🎜
12🎜🎜
클래스 로리걸 {🎜
🎜
}🎜
🎜
클래스 소년 {🎜
보호됨 $girl;🎜
🎜
code><code class="php 키워드">공개 함수 __construct() {🎜
// $this->girl = new Girl(); // 죄송합니다.. .🎜
$this->girl = new LoliGirl();🎜
}🎜
}🎜🎜🎜🎜🎜🎜

어느 날 소년은 유 자매와 사랑에 빠졌습니다.... 소년은 너무 짜증났습니다. . .

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🎜
인터페이스 소녀 { 🎜
// 소년은 나에게 몇 가지 능력이 있다는 것을 알아야 합니다.🎜 }🎜
🎜
클래스 LoliGril 구현 소녀 {🎜
// 소녀의 능력을 구현하겠습니다.🎜
} code >🎜<div class="line number8 index7 alt1"> 🎜<div class="line number9 index8 alt2"> <code class="php 키워드">클래스 빅센 Girl 구현 {🎜
// Vixen은 확실히 여자입니다. 의심하지 마세요.🎜
}🎜
🎜
클래스 소년 {🎜
보호됨 $girl ; 🎜
🎜
공개 함수 __construct(소녀 $girl ) {🎜
$ this->girl = $girl;🎜<div class="line number18 index17 alt1"> <code class="php space"> }🎜
}🎜
🎜
$loliGirl = LoliGirl();🎜<div class="line number22 index21 alt1"> <code class="php 변수">$vixen = new Vixen();🎜
🎜
$boy = 소년($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;🎜🎜    비공개 $file;🎜🎜 🎜🎜    함수 setdb($db) {🎜🎜        $this->db = $db ;🎜🎜    }🎜🎜 🎜 🎜    함수 setfile($file) {🎜🎜        $this->file = $file; 🎜🎜}}🎜🎜}🎜🎜 🎜🎜클래스 파일 {🎜🎜}🎜🎜 🎜🎜클래스 db {🎜🎜}🎜🎜 🎜🎜// ...🎜🎜 🎜🎜클래스 테스트 {🎜🎜     $book new Book();🎜
    $book->setdb(new db());
    $book->setfile(new file());
}

요약:

대부분의 애플리케이션은 비즈니스 로직을 구현하기 위해 서로 협력하는 두 개 이상의 클래스로 구성되기 때문에 각 개체는 자신이 협력하는 개체(즉, 자신이 속한 개체)를 얻어야 합니다. 종속 개체에 대한 참조)와 협력합니다. 이 획득 프로세스가 자체적으로 구현되면 코드가 고도로 결합되어 유지 관리 및 디버깅이 어려워집니다.

그래서 우리는 종속성 주입이라는 개념을 갖게 되었습니다. 종속성 주입은 다음과 같은 문제를 해결합니다.

  • 종속성 간의 분리

  • Mock에 편리한 단위 테스트

위 두 가지 방법의 코드는 매우 하지만 많은 종속성을 주입해야 하는 경우에는 많은 줄을 추가해야 한다는 의미이므로 관리하기가 더 어려워집니다.

더 나은 솔루션은 모든 종속성에 대한 컨테이너로 클래스를 생성하는 것입니다. 이 클래스에서는 필요한 종속성을 저장, 생성, 획득 및 찾을 수 있습니다. 먼저 IOC

제어 반전(IOC)

제어 반전은 컴퓨터 코드 간의 결합을 줄이는 데 사용할 수 있는 객체 지향 프로그래밍의 설계 원리입니다. 가장 일반적인 방법은 DependencyInjection(DI)이고 다른 하나는 "Dependency Lookup"입니다. 제어 역전을 통해 객체가 생성되면 시스템의 모든 객체를 제어하는 ​​외부 엔터티가 자신이 의존하는 객체의 참조를 전달합니다. 의존성이 객체에 주입된다고도 말할 수 있습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

11
1213}}

이때, book 인스턴스를 얻으려면 $newone = Ioc::makebook();

만 실행하면 됩니다. 위는 컨테이너의 특정 인스턴스이므로 구체적으로 작성하지 않는 것이 가장 좋습니다. 의존성 주입 방법을 사용하여 레지스트리에 등록하고 얻는 것이 좋습니다.

21
22
14
<?php
클래스 Ioc {< /code></div><div class="line number6 index5 alt1"><code class="php space"> 보호됨 $db_conn;
공개 static 함수 make_book() {
</code code> 코드><code class="php 변수">$new_book = Book();
$new_book->set_db(self::$db_conn);
//...
//...
//기타 종속성 주입
반환 $new_book; 코드 >
}
<?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;
    }
}
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
/**
 * 控system反转类
  코드><code class="php 주석">*/
클래스 Ioc {
/**
* @var 배열 등록 종속성 배열
*/
보호됨 정적 $registry = 배열 code><code class="php plain">();
/**
* 레지스트리 배열에 해결(익명 함수) 추가
*
* @param string $name 종속성 식별자
* @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($namestatic::$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. 참가자는 누구인가요?

답변: 일반적으로 세 부분이 있는데, 하나는 객체이고, 다른 하나는 객체의 외부 리소스입니다. 명사에 대해 다시 설명하겠습니다. 객체는 일반적인 Java 객체를 참조하며, IoC/DI 컨테이너는 단순히 IoC/DI 기능을 구현하는 데 사용되는 프레임워크 프로그램을 참조합니다. 개체 외부에서 개체에 필요한 다른 개체 또는 개체에 필요한 파일 리소스 등과 같이 집합적으로 리소스라고 합니다.

2. 의존성: 누가 누구에게 의존하나요? 종속성이 있는 이유는 무엇입니까?

답변: 객체는 IoC/DI 컨테이너에 따라 다릅니다. 프로젝트에서는 다양한 클래스 사이에 다양한 관계가 존재하며, 이들 모두가 완전히 독립적일 수는 없으므로 종속성을 형성합니다. 기존 개발에서는 다른 클래스를 사용할 때 직접 호출을 사용했는데, 이는 강력한 결합을 형성하므로 피해야 합니다. 종속성 주입은 컨테이너를 빌려 종속 개체를 전송하여 분리를 달성합니다.

3. 주사: 누가 누구에게 주사하나요? 정확히 무엇을 주입하나요?

답변: 컨테이너를 통해 객체에 필요한 외부 리소스를 주입합니다

4. 제어 역전: 누가 누구를 제어합니까? 무엇을 통제하나요? 왜 반전이라고 불리는가?

답변: IoC/DI 컨테이너 제어 객체는 주로 객체 인스턴스 생성을 제어합니다. 반전은 양의 방향에 상대적이므로 양의 방향으로 간주되는 것은 무엇입니까? 일반적인 상황에서 애플리케이션을 생각해 보세요. A 내부에서 C를 사용하려면 어떻게 하시겠습니까? 물론 C의 객체는 직접 생성된다. 즉, 필요한 외부자원 C를 클래스 A에서 적극적으로 획득하는 상황을 포워드(forward)라고 한다. 그렇다면 반전은 무엇인가? 즉, 클래스 A는 더 이상 C를 적극적으로 획득하지 않고 IoC/DI 컨테이너가 C의 인스턴스를 획득할 때까지 수동적으로 기다린 다음 이를 역으로 클래스 A에 주입합니다.

5. 의존성 주입과 제어 역전은 동일한 개념인가요?

답변: 위에서 볼 수 있듯이 종속성 주입은 애플리케이션의 관점에서 설명됩니다. 종속성 주입은 더 자세히 설명할 수 있습니다. 애플리케이션은 컨테이너에 의존하여 필요한 외부 리소스를 생성하고 주입합니다. 제어 반전은 컨테이너의 관점에서 설명이 완료됩니다. 컨테이너는 애플리케이션을 제어하고, 컨테이너는 역으로 애플리케이션에 필요한 외부 리소스를 애플리케이션에 주입합니다.

위 내용은 PHP 종속성 주입(DI) 및 제어 반전(IoC) 예제 튜토리얼의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
이전 기사:PHP7의 기능은 무엇입니까 다음 기사:PHP에 대한 사전 이해 - 캡슐화, 상속, 다형성 기능
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
최신 이슈
관련 주제
더>
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿