programing

IoC 컨테이너 및 종속성 주입 이해

oldcodes 2023. 10. 21. 10:49
반응형

IoC 컨테이너 및 종속성 주입 이해

이해합니다.

  • 종속성은 클래스 A의 인스턴스가 클래스 A의 새 인스턴스를 인스턴스화하기 위해 클래스 B의 인스턴스를 필요로 하는 경우입니다.
  • 종속성 주입은 클래스 A가 클래스 B의 인스턴스를 통과할 때 또는 클래스의 매개 변수를 통해A의 생성자 또는 set~DependencyName을 통해 생성됩니다.여기~(~DependencyName)여기~ $param) 함수입니다.(이것은 제가 완전히 확신할 없는 분야하나입니다.)
  • IoC 컨테이너는 단일 톤 클래스(한 번에 인스턴스화된 인스턴스 하나만 가질 수 있음)로, 이 프로젝트에 대해 해당 클래스의 개체를 인스턴스화하는 특정 방법을 등록할 수 있습니다.여기 제가 사용하고 있는 IoC 컨테이너에 대한 클래스 정의와 함께 설명하려는 내용의 예에 대한 링크가 있습니다.

그래서 이 시점에서 좀 더 복잡한 시나리오를 위해 IoC 컨테이너를 사용하기 시작했습니다.IoC 컨테이너를 사용하기 위해서는 IoC 컨테이너에 정의하고 싶은 종속성을 가진, 만들고 싶은 거의 모든 클래스에 대한 has-a 관계로 제한됩니다.클래스를 상속받는 클래스를 만들고 싶은데 특정 방법으로 부모 클래스가 생성된 경우에만 IoC 컨테이너에 등록된 경우에는 어떻게 해야 합니까?

예를 들어 다음과 같습니다.mysqli의 자식 클래스를 만들고 싶지만, 이 클래스를 IoC 컨테이너에 등록하여 이전에 IoC 컨테이너에 등록한 방식으로 구성된 부모 클래스로만 인스턴스화하려고 합니다.코드를 복제하지 않고 이를 수행할 수 있는 방법을 생각할 수 없습니다(그리고 이는 학습 프로젝트이기 때문에 가능한 한 '순수'로 유지하려고 합니다).다음은 제가 설명하려는 것에 대한 몇 가지 예시입니다.

그럼 여기 제 질문 몇 가지가 있습니다.

  • OOP의 원칙을 깨지 않고 위에서 하려고 하는 것이 가능합니까?저는 c++에서 동적 메모리와 복사 생성기를 사용하여 이를 수행할 수 있다는 것을 알고 있지만, php에서는 그런 종류의 기능을 찾을 수 없었습니다. (__construct 외에 다른 마법 방법을 사용해 본 경험이 거의 없다는 것을 인정하지만, 제대로 이해했다면 읽기와 __clone에서,인스턴스화되는 자식 클래스를 부모 클래스 인스턴스의 클론으로 만드는 데 생성자에서 사용할 수 없습니다.
  • IoC와 관련하여 내 모든 종속성 클래스 정의는 어디로 가야 합니까?(내 IoC를 사용해야 함.php 상단에 require_once('dependencyClassDefinition.php')가 많이 있습니까?제 직감적인 반응은 더 좋은 방법이 있지만 아직 생각해내지 못했다는 것입니다.)
  • 개체를 어떤 파일에 등록해야 합니까?클래스 정의 후 IoC.php 파일에서 IoC::register()에 대한 모든 호출을 수행 중입니다.
  • 해당 종속성이 필요한 클래스를 등록하기 전에 IoC에 종속성을 등록해야 합니까?IoC에 등록된 개체를 실제로 인스턴스화하기 전까지는 익명 기능을 실행하지 않기 때문에, 아마 그렇지 않을 것으로 생각되지만, 여전히 우려됩니다.
  • 또 제가 간과하고 있는 것이 있거나 사용해야 하는 것이 있습니까?한 번에 한 단계씩 나아가려고 노력하고 있지만, 제 코드가 재사용될 수 있다는 것과 제 프로젝트에 대해 아무것도 모르는 사람이 그것을 읽고 이해할 수 있다는 것을 알고 싶지도 않습니다.

간단히 말하면 (OOP 세계에만 국한된 문제가 아니기 때문에), 의존성이란 구성 요소 A가 해야 할 일을 하기 위해 구성 요소 B가 필요한 (의존적인) 상황입니다.이 단어는 이 시나리오에서 의존적 구성요소를 설명하는 데에도 사용됩니다.이를 OOP/PHP 용어로 표현하자면, 의무 자동차 비유와 함께 다음 예를 고려해 보십시오.

class Car {

    public function start() {
        $engine = new Engine();
        $engine->vroom();
    }

}

Car 달려 있습니다Engine.Engine이다.Car종속성하지만 이 코드 조각은 꽤나 좋지 않습니다. 왜냐하면:

  • 의존성은 암묵적입니다; 당신이 검사하기 전까지는 당신은 그것이 거기에 있다는 것을 모릅니다.Car의 코드
  • 클래스가 긴밀하게 결합되어 있습니다; 당신은 그것을 대체할 수 없습니다.Engine와 함께MockEngine시험 목적으로 또는TurboEngine원래의 것을 수정하지 않고 확장하는 것.Car.
  • 자동차가 스스로 엔진을 만들 수 있다는 것은 좀 우스꽝스러워 보입니다, 그렇죠?

의존성 주입은 이 모든 문제를 해결하는 방법입니다.Car요가 합니다.Engine다음 중 하나를 명시적 및 명시적으로 제공합니다.

class Car {

    protected $engine;

    public function __construct(Engine $engine) {
        $this->engine = $engine;
    }

    public function start() {
        $this->engine->vroom();
    }

}

$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);

위는 종속성(의존 객체)이 클래스 생성자를 통해 종속(소비자)에게 제공되는 생성자 주입의 예시입니다.또 다른 방법은 한가지를 노출시키는 것일 것입니다.setEngine메소드 인 더Car클래스 및 이를 사용하여 예를 주입합니다.Engine. 이를 setter injection이라고 하며 런타임에 스왑해야 하는 종속성에 주로 유용합니다.

사소하지 않은 모든 프로젝트는 상호 의존적인 구성 요소로 구성되어 있으며, 매우 빠르게 주입되는 것을 쉽게 이해할 수 있습니다.종속성 주입 컨테이너는 다른 개체를 인스턴스화하고 구성하는 방법을 알고 프로젝트의 다른 개체와의 관계를 알고 있으며 종속성 주입을 대신 수행하는 개체입니다.이를 통해 프로젝트의 모든 (인터) 의존성을 중앙 집중식으로 관리할 수 있으며, 코드의 여러 곳을 편집할 필요 없이 하나 이상의 의존성을 변경/모킹할 수 있습니다.

자동차의 비유를 버리고 OP가 예로 이루고자 하는 바를 살펴봅시다.예를 들면 우리가.Database에 따라 대상mysqli물건.우리가 정말 원시적인 의존성 검사 컨테이너 클래스를 사용하고 싶다고 가정해 보겠습니다.DIC두 가지 방법을 보여줍니다.register($name, $callback)지정된 이름으로 객체를 생성하는 방법을 등록하고,resolve($name)그 이름에서 개체를 가져오는 것입니다.컨테이너 설정은 다음과 같습니다.

$dic = new DIC();
$dic->register('mysqli', function() {
    return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
    return new Database($dic->resolve('mysqli'));
});

우리 컨테이너에 우리가 한 예를 가져가라고 하는 것을 주목하세요.mysqli 자체로 하나의 예를 모았습니다.Database. 그 다음에 A를.Database예를 들어 종속성이 자동으로 주입되면 간단히 다음과 같습니다.

$database = $dic->resolve('database');

그게 요점입니다.PHP DI/IoC 컨테이너는 다소 정교하지만 비교적 간단하고 쉽게 파악할 수 있는 Pimple입니다.자세한 예는 설명서를 확인합니다.


OP의 코드와 질문에 관해:

  • 컨테이너에 정적 클래스나 싱글톤을 사용하지 마십시오. 둘 다 악입니다.대신 Pimple을 확인해보세요.
  • 당신이 당신의 것을 원하는지 결정하세요.mysqliWrapper학급 증설 mysql의지할 수도 있고요
  • 전화로IoC내부로부터mysqliWrapper한 의존관계를 다른 의존관계로 바꾸는 겁니다개체가 컨테이너를 인식하거나 사용하지 않아야 합니다. 그렇지 않으면 DIC가 더 이상 서비스 로케이터(안티) 패턴입니다.
  • 그럴 필요 없어요require컨테이너에 등록하기 전에 해당 클래스의 개체를 사용할지 여부를 전혀 알 수 없기 때문에 클래스 파일을 저장합니다.모든 컨테이너 설정을 한 곳에서 수행합니다.오토로더를 사용하지 않으면,require컨테이너에 등록하는 익명 함수의 내부.

추가 리소스:

언급URL : https://stackoverflow.com/questions/18562752/understanding-ioc-containers-and-dependency-injection

반응형