oop 장점 - Inversion of Control이란 무엇입니까?




스프링 컨테이너 (25)

Inversion of Control (또는 IoC)은 처음 발생할 때 매우 혼란 스러울 수 있습니다.

  1. 이게 뭐야?
  2. 어떤 문제가 해결됩니까?
  3. 적절한시기와 그렇지 않은 경우는 언제입니까?

Answers

Inversion of Controls는 관심사를 분리하는 것입니다.

IoC없이 : 랩톱 컴퓨터를 가지고 실수로 화면이 깨집니다. 그리고, 당신은 동일한 모델의 노트북 화면이 시장 어디에도 없다는 것을 알게됩니다. 그래서 너는 붙어있다.

IoC 사용 : 데스크톱 컴퓨터가 있고 우연히 화면이 깨집니다. 시장에서 거의 모든 데스크탑 모니터를 가져올 수 있으며 데스크톱과도 잘 작동합니다.

이 경우 데스크톱이 IoC를 성공적으로 구현합니다. 다양한 종류의 모니터를 사용할 수 있지만 노트북은 그렇지 않습니다. 고정 스크린을 사용해야합니다.


예를 들어, 작업 # 1은 객체를 생성하는 것입니다. IOC 개념이 없다면, task # 1은 Programmer에 의해 수행되어야한다. 그러나 IOC 개념으로, task # 1은 컨테이너에 의해 수행 될 것이다.

짧은 컨트롤은 프로그래머에서 컨테이너로 반전됩니다. 그래서 그것은 제어의 반전이라고합니다.

좋은 예가 하나 here .


나는이 설명을 좋아한다 : http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

간단하게 시작하고 코드 예제도 보여줍니다.

소비자 X는 무언가를 성취하기 위해 소비 클래스 Y가 필요합니다. 그것은 모두 훌륭하고 자연스럽지 만, X는 실제로 Y를 사용한다는 것을 알아야합니까?

X가 행동을 구현하는 사람을 모른 채 Y의 행동, 메서드, 속성 등을 가진 무언가를 사용한다는 것을 X가 알고 있다는 것만으로 충분하지 않습니까?

아래의 그림과 같이 Y에서 X가 사용하는 동작의 추상 정의를 추출하고 소비자 X가 Y 대신 해당 인스턴스를 사용하게하면 Y에 대한 구체적인 내용을 알지 않고도 계속 수행 할 수 있습니다.

위 그림에서 I와 X는 I의 인스턴스를 사용합니다. X가 여전히 Y를 사용할 가능성이있는 반면 흥미로운 점은 X가 그것을 알지 못한다는 것입니다. 그것은 단지 그것이 I를 구현하는 것을 사용한다는 것을 알고 있습니다.

다음과 같은 혜택에 대한 자세한 정보 및 설명을 보려면 기사를 읽으십시오.

  • X는 Y에 더 이상 의존하지 않습니다.
  • 보다 융통성있게, 런타임에서 구현을 결정할 수 있습니다.
  • 코드 단위 격리,보다 쉬운 테스트

...


IoC는 코드와 제 3 자 코드 (라이브러리 / 프레임 워크) 간의 관계를 바꾸는 것에 관한 것입니다.

  • 일반적인 s / w 개발에서는 main () 메서드를 작성하고 "library"메서드를 호출합니다. 당신 은 통제하에 있습니다 :)
  • IoC에서 "프레임 워크"는 main ()을 제어하고 메서드를 호출합니다. 프레임 워크 가 제어 할 수 있습니다 :(

DI (Dependency Injection)는 어플리케이션에서 컨트롤이 어떻게 움직이는 지에 대한 것입니다. 전통적인 데스크탑 애플리케이션은 애플리케이션 (main () 메소드)에서 다른 라이브러리 메소드 호출로의 제어 흐름을 가졌지 만, DI 제어 흐름은 반대로 프레임 워크가 앱을 시작하고, 초기화하고, 필요할 때마다 메소드를 호출합니다.

결국 당신은 항상 승리 :)


당신이 객체라고 가정하십시오. 그리고 너는 식당에 간다.

IoC가 없으면 : "사과"를 요구하고, 더 많이 물을 때 항상 사과를 먹습니다.

IoC : "과일"을 요구할 수 있습니다. 당신은 봉사 할 때마다 다른 과일을 얻을 수 있습니다. 예 : 사과, 오렌지 또는 수박.

그래서 IoC가 다양성을 좋아할 때 선호됩니다.


IoC / DI는 호출 객체에 의존성을 밀어 낸다. 슈퍼 간단합니다.

비 기술적 인 대답은 당신이 그것을 켜기 바로 전에 차에서 엔진을 바꿀 수있는 것입니다. 모든 것이 올바르게 연결되면 (인터페이스), 당신은 좋다.


  1. 그래서 1 above . above

  2. 유지 관리가 가장 좋은 방법입니다. 그것은 두 클래스가 서로 친밀하지 않도록 인터페이스를 사용하고 있음을 보장합니다.

캐슬 윈저 (Castle Windsor)와 같은 컨테이너를 사용할 때 유지 관리 문제를 더욱 효과적으로 해결합니다. 코드 줄을 변경하지 않고 파일 기반 지속성을 사용하는 데이터베이스로 이동하는 구성 요소를 교체 할 수 있다는 것은 매우 기막힌 일입니다.

일단 제네릭에 들어가면 더 나아질 것입니다. 레코드를 받고 메시지를 게시하는 메시지 게시자가 있다고 가정 해보십시오. 게시 내용에 상관하지 않지만 레코드에서 메시지로 무언가를 가져 오는 데는 매퍼가 필요합니다.

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

한 번 썼지 만 다른 유형의 메시지를 게시하면이 코드 집합에 여러 유형을 주입 할 수 있습니다. 같은 유형의 레코드를 다른 메시지에 매핑하는 맵퍼도 작성할 수 있습니다. Generics에서 DI를 사용하면 많은 작업을 수행 할 수있는 코드를 거의 작성할 수 없습니다.

오 예, 테스트 가능성에 대한 우려가 있지만 IoC / DI의 이점에 부수적입니다.

IoC / DI가 분명히 좋아합니다.

삼 .좀 더 복잡한 프로젝트를 중간 크기로 만들면 더욱 적절 해집니다. 나는 당신이 고통을 느끼기 시작할 때가 적절해진다 고 말할 것입니다.


Inversion of Control이란 무엇입니까?

이 간단한 두 단계를 수행하면 제어 반전이 완료됩니다.

  1. 할 일 부분과 일 부분을 구분하십시오.
  2. 부품이 어떤 부분을 ​​가능한 한 적게 알고 있는지 확인하십시오. 그 반대.

구현을 위해 사용중인 기술 / 언어를 기반으로 각 단계에 대해 가능한 여러 기술이 있습니다.

-

Inversion of Control (IoC)의 반전 부분은 혼란스러운 것입니다. 반전 은 상대적인 용어이기 때문에. IoC를 이해하는 가장 좋은 방법은 그 단어를 잊는 것입니다!

-

예제들

  • 이벤트 처리. 이벤트 핸들러 (할 일 부분) - 이벤트 발생 (할 일 부분)
  • 인터페이스. 컴포넌트 클라이언트 (할 부분) - 컴포넌트 인터페이스 구현 (할 일 부분)
  • x 고정 장치. 설치 및 TearDown (할 일 부분) - 처음에는 xUnit 프레임 워크가 설치 프로그램을 호출하고 끝에는 TearDown을 호출합니다 (할 부분)
  • 템플릿 방법 디자인 패턴. 템플릿 메소드 수행 할 부분 - 프리미티브 서브 클래스 구현 what-to-do part
  • COM의 DLL 컨테이너 메서드입니다. DllMain, DllCanUnload 등 (할 일 부분) - COM / OS (할 부분)

말하기 프로그래밍

쉬운 용어로 IoC : 특정 클래스 (예 : 필드 또는 매개 변수)를 일부 클래스에서 사용할 수있는 와일드 카드로 사용하는 인터페이스입니다. 그것은 코드의 재사용을 가능하게합니다.

예를 들어 DogCat의 두 클래스가 있다고 가정 해 봅시다 . 두 사람 모두 나이, 크기, 체중과 같은 자질 / 상태를 공유합니다. 그래서 대신 호출 서비스 클래스 만드는 DogServiceCatService을 , 나는 하나 하나라는 만들 수 있습니다 AnimalService 그들이 인터페이스를 사용하는 경우에만 개와 고양이를 사용할 수 있습니다 IAnimal을 .

그러나, 실용적인 말로하면, 그것은 거꾸로있다.

a) 대부분의 개발자는 그것을 사용하는 방법을 모른다 . 예를 들어, 나는라는 클래스 만들 수 있습니다 고객내가 자동으로 생성 할 수 있습니다 라는 인터페이스 (IDE의 도구 사용) ICustomer을 . 따라서 인터페이스가 재사용되는지 여부와 관계없이 클래스와 인터페이스로 채워진 폴더를 찾는 일은 드문 일이 아닙니다. 그것은 BLOATED라고 불립니다. 어떤 사람들은 "미래에 사용할 수 있을지도 모른다"라고 주장 할 수 있습니다. : - |

b) 제한이있다. 예를 들어 Dog and Cat 의 사례에 대해 이야기하고 만을위한 새로운 서비스 (기능)를 추가하겠습니다. 개를 훈련 시키는데 필요한 일수를 계산하고 싶다고하자 trainDays(). 고양이는 쓸모가없고, 고양이는 훈련받을 수 없다. (농담).

b.1) trainDays()서비스 AnimalService에 추가 하면 고양이와도 작동하며 전혀 유효하지 않습니다.

b.2) trainDays()어떤 클래스가 사용되는지 평가할 때 조건을 추가 할 수 있습니다 . 그러나 IoC는 완전히 깨질 것입니다.

b.3) 새로운 기능을 위해서 DogService 라는 새로운 서비스 클래스를 만들 수 있습니다 . 그러나 Dog 의 경우 두 클래스의 서비스 (유사한 기능 포함)를 사용하게되므로 코드 유지 관리가 향상됩니다 .


  1. Wikipedia 기사 . 나에게 제어 반전은 순차적으로 작성된 코드를 위임 구조로 변환하는 것입니다. 프로그램이 모든 것을 명시 적으로 제어하는 ​​대신, 프로그램은 특정 일이 발생할 때 호출되는 특정 기능을 가진 클래스 또는 라이브러리를 설정합니다.

  2. 코드 중복을 해결합니다. 예를 들어, 예전에는 수동으로 이벤트 루프를 작성하여 새로운 이벤트에 대한 시스템 라이브러리를 폴링했습니다. 요즘 대부분의 최신 API는 시스템 라이브러리에 관심있는 이벤트를 알려주고 발생 시점을 알려줍니다.

  3. 컨트롤의 반전은 코드 중복을 줄이는 실용적인 방법이며 전체 메서드를 복사하고 코드의 작은 부분 만 변경하는 경우 제어 반전으로이를 해결할 수 있습니다. 제어 반전은 대리자, 인터페이스 또는 원시 함수 포인터의 개념을 통해 여러 언어에서 쉽게 수행 할 수 있습니다.

    모든 경우에 사용하는 것은 적절하지 않습니다. 프로그램의 흐름이 이와 같이 작성 될 때 따라하기가 더 어려울 수 있기 때문입니다. 재사용 될 라이브러리를 작성할 때 메소드를 설계하는 유용한 방법이지만, 코드 중복 문제를 실제로 해결하지 않는 한 자신의 프로그램의 핵심 부분에 사용되어야합니다.


Inversion of Control (IoC) 및 Dependency Injection (DI) 패턴은 모두 코드에서 종속성을 제거하는 것입니다.

예를 들어, 응용 프로그램에 텍스트 편집기 구성 요소가 있고 맞춤법 검사를 제공하려고한다고 가정하십시오. 표준 코드는 다음과 같습니다.

public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}

우리가 여기서 한 것은 TextEditorSpellChecker 사이의 의존성을 만듭니다. IoC 시나리오에서는 대신 다음과 같은 작업을 수행합니다.

public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}

첫 번째 코드 예제에서는 SpellChecker ( this.checker = new SpellChecker(); )를 인스턴스화 SpellChecker this.checker = new SpellChecker(); 즉, TextEditor 클래스가 SpellChecker 클래스에 직접 종속되어 있음을 의미합니다.

두 번째 코드 예제에서는 TextEditor 생성자 시그너처에 SpellChecker 종속성 클래스를 사용하여 추상화를 만듭니다 (클래스의 종속성을 초기화하지 않음). 이렇게하면 종속성을 호출하여 다음과 같이 TextEditor 클래스에 전달할 수 있습니다.

SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);

이제 TextEditor 클래스를 만드는 클라이언트는 TextEditor 시그니처에 종속성을 주입하기 때문에 SpellChecker 구현에서 사용할 제어 권한을 갖습니다.

이것은 간단한 예일뿐입니다. Simone Busoli 의 기사 시리즈에 자세히 설명되어 있습니다.


클래스 내에서 객체를 생성하는 것은 tight coupling이라고 불리며, Spring은 디자인 패턴 (DI / IOC)에 따라 이러한 의존성을 제거합니다. 클래스의 어떤 객체가 클래스에서 생성되는 것이 아니라 생성자에서 전달되는지. 보다 일반적인 구조를 정의하기 위해 생성자에서 수퍼 클래스 참조 변수를 제공합니다.


첫 번째 부분에만 응답합니다. 이게 뭐야?

제어 반전 (Inversion of Control, IoC)은 먼저 클래스 인스턴스를 생성 한 다음 종속 인스턴스를 생성하는 클래스 인스턴스를 생성하는 대신 클래스의 첫 번째 인스턴스와 후자의 인스턴스를 생성하는 것을 의미합니다 (선택적으로 생성자를 통해 삽입). 따라서 제어 반전 은 프로그램 제어흐름을 역전시킵니다. 의존성을 만드는 동안 제어 흐름을 제어 하는 호출 수신자 대신 호출자가 프로그램 제어 흐름을 제어합니다 .


Inversion of Control을 사용하기 전에 장단점이 있다는 사실을 잘 알고 있어야하며, 그렇게 할 경우 왜 사용 하는지를 알아야합니다.

장점 :

  • 인터페이스 구현을 다른 구현과 쉽게 교환 할 수 있도록 코드가 분리됩니다.
  • 구현 대신 인터페이스에 대한 코딩에 강한 동기 부여
  • 코드에 대한 단위 테스트를 작성하는 것은 매우 쉽습니다. 왜냐하면 생성자 / 설정자에서 받아 들인 객체 이외에는 아무 것도 의존하지 않고 올바른 객체를 격리하여 쉽게 초기화 할 수 있기 때문입니다.

단점 :

  • IoC는 프로그램의 제어 흐름을 반전시킬뿐만 아니라 상당히 흐리게 만듭니다. 즉, 더 이상 코드를 읽지 않고 한 곳에서 다른 곳으로 이동할 수 있습니다. 이는 코드에 일반적으로 포함될 연결이 더 이상 코드에 없기 때문입니다. 대신 XML 구성 파일이나 주석 및 이러한 메타 데이터를 해석하는 IoC 컨테이너의 코드에 있습니다.
  • XML 설정이나 주석을 잘못 만든 새로운 클래스의 버그가 발생하고 IoC 컨테이너가 특정 조건에서 객체 중 하나에 Null 참조를 삽입하는 이유를 찾는 데 많은 시간을 할애 할 수 있습니다.

개인적으로 나는 IoC의 장점을보고 정말로 좋아하지만 IoC를 가능한 한 피하는 경향이 있습니다. 소프트웨어를 더 이상 "실제"프로그램을 구성하지 않는 클래스 모음으로 바꾸기 때문입니다. XML 구성 또는 주석 메타 데이터가 없으며이를 제외하고는 떨어질 것입니다.


Inversion of Control은 프로그램 콜백 (예 : GUI 프로그램)을 할 때 얻을 수있는 기능입니다.

예를 들어, 구식 학교 메뉴에서 다음과 같이 할 수 있습니다.

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

사용자 상호 작용의 흐름을 제어한다.

GUI 프로그램 또는 일부에서는 대신 다음과 같이 말합니다.

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

이제 제어가 반대로됩니다 ... 컴퓨터가 고정 된 순서로 사용자 입력을받는 대신 사용자가 데이터가 입력되는 순서와 데이터가 데이터베이스에 저장되는 순서를 제어합니다.

기본적으로 이벤트 루프, 콜백 또는 실행 트리거가있는 모든 항목이이 범주에 속합니다.


우리가 어떤 호텔에서 어떤 만남을 가졌다 고하자.

많은 사람들, 물이 많은 카페인, 많은 플라스틱 컵.

누군가 마실 때 컵을 채우고 마시고 바닥에 컵을 던지십시오.

시간이 지나면 우리는 플라스틱 컵과 물로 바닥을 덮습니다.

반전 제어하자.

같은 장소에서 같은 모임이 있지만 플라스틱 컵 대신에 한 잔의 웨이터 (싱글 톤)가있는 웨이터가 있습니다.

그리고 그녀는 항상 손님들에게 술을 제공합니다.

누군가 마실 것을 원하면 웨이터 글래스에서 음료를 마시고 웨이터에게 돌려 보내십시오.

위생의 문제를 떠나서 마시는 과정 통제의 마지막 형태는 훨씬 더 효과적이고 경제적입니다.

그리고 이것이 바로 Spring (다른 IoC 컨테이너, 예 : Guice)이하는 일입니다. 새로운 키워드 (플라스틱 컵 복용)를 사용하여 응용 프로그램을 작성하는 대신 Spring IoC 컨테이너는 항상 필요한 객체 (물의 유리)와 동일한 인스턴스 (싱글 톤)를 제공합니다.

그러한 모임의 주최자로 생각하십시오. 호텔 행정부에 메시지를 보내는 방법이 필요합니다.

회의 참석자는 물 한 잔은 필요하지만 케이크 조각은 필요치 않습니다.

예:-

public class MeetingMember {

    private GlassOfWater glassOfWater;

    ...

    public void setGlassOfWater(GlassOfWater glassOfWater){
        this.glassOfWater = glassOfWater;
    }
    //your glassOfWater object initialized and ready to use...
    //spring IoC  called setGlassOfWater method itself in order to
    //offer to meetingMember glassOfWater instance

}

유용한 링크:-


나는이 두 용어에 대한 나의 간단한 이해를 적어 둘 것이다.

For quick understanding just read examples*

의존성 주입 (DI) :
의존성 주입은 일반적으로 메소드가 의존 객체를 생성하는 대신 메소드가 의존하는 객체를 매개 변수로 전달하는 것을 의미 합니다 .
실제로이 방법은 특정 구현에 직접 의존하지 않는다는 것을 의미합니다. 요구 사항을 충족시키는 모든 구현을 매개 변수로 전달할 수 있습니다.

이 객체를 사용하면 의존 관계를 알 수 있습니다. 그리고 봄이 그것을 가능하게합니다.
이는 느슨하게 결합 된 응용 프로그램 개발로 이어집니다.

Quick Example:EMPLOYEE OBJECT WHEN CREATED,
              IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
   (if address is defines as dependency by Employee object)

Inversion of Control (IoC) 컨테이너 :
이것은 프레임 워크의 일반적인 특징이며, IOC 는 자바 객체를 관리합니다.
- 인스턴스화에서 BeanFactory를 통한 파기.
IoC 컨테이너에 의해 인스턴스화 된 Java 구성 요소는 Bean이라고하며 IoC 컨테이너는 Bean의 범위, 라이프 사이클 이벤트 및 구성되고 코딩 된 AOP 기능관리합니다 .

QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it .

Inversion of Control을 구현함으로써 소프트웨어 / 객체 소비자는 제어되거나 옵션이 적게 드는 대신 소프트웨어 / 객체에 대한 더 많은 제어 / 옵션을 얻습니다.

설계 가이드 라인으로서의 제어 반전은 다음과 같은 목적을 위해 사용됩니다.

특정 작업의 실행을 구현과 분리하는 방법이 있습니다.
모든 모듈은 자신이 의도 한 것에 집중할 수 있습니다.
모듈은 다른 시스템이하는 일에 대한 가정을하지 않고 계약에 의존합니다.
모듈 교체는 다른 모듈에 부작용이 없습니다.
나는 여기에 추상적 인 것들을 유지할 것이다. 당신은 주제에 대한 세부적인 이해를 위해 다음의 링크를 방문 할 수있다.
보기 좋은 예

상해


개념을 이해하기 위해 IoC (Inversion of Control) 또는 DIP (Dependency Inversion Principle)에는 추상화 및 반전이라는 두 가지 작업이 포함됩니다. DI (Dependency Injection)는 반전 방법 중 몇 가지 중 하나 일뿐입니다.

이것에 관해 더 많이 읽는 것은 당신은 나의 blog를 Here 읽을 수있다 Here

  1. 이게 뭐야?

실제 동작을 경계 (객체 지향 프로그래밍의 클래스) 외부에서 가져 오는 연습입니다. 경계 엔티티는 추상화 (예 : 인터페이스, 추상 클래스, 객체 지향 프로그래밍의 위임) 만 알고 있습니다.

  1. 어떤 문제가 해결됩니까?

프로그래밍의 관점에서 IoC는 모 놀리 식 코드를 모듈화하고 여러 부분을 분리하고 단위 테스트 할 수 있도록함으로써 모 놀리 식 코드를 해결하려고합니다.

  1. 적절한시기와 그렇지 않은 경우는 언제입니까?

모 놀리 식 코드 (예 : 매우 간단한 프로그램)가 필요한 상황이 아니라면 대부분의 경우에 적합합니다.


  1. 반전 제어는 시스템의 구성 요소와 레이어를 분리하는 데 사용되는 패턴입니다. 패턴은 구성 요소가 구성 될 때 구성 요소에 종속성을 주입하여 구현됩니다. 이러한 종속성은 일반적으로 추가 디커플링 및 테스트 가능성 지원을위한 인터페이스로 제공됩니다. Castle Windsor, Unity와 같은 IoC / DI 컨테이너는 IoC를 제공하는 데 사용할 수있는 도구 (라이브러리)입니다. 이러한 도구는 수명, AOP / 차단, 정책 등 간단한 종속성 관리 이상의 확장 된 기능을 제공합니다.

  2. 에이. 구성 요소가 종속성을 관리하는 것을 책임지지 않도록합니다.
    비. 다양한 환경에서 종속성 구현을 스왑하는 기능을 제공합니다.
    기음. 종속성 조롱을 통해 구성 요소를 테스트 할 수 있습니다.
    디. 응용 프로그램 전체에서 자원을 공유하기위한 메커니즘을 제공합니다.

  3. 에이. 테스트 중심 개발을 수행 할 때 중요합니다. IoC가 없으면 테스트중인 구성 요소가 나머지 시스템에 많이 연결되어 있기 때문에 테스트가 어려울 수 있습니다.
    비. 모듈러 시스템을 개발할 때 중요합니다. 모듈 식 시스템은 재 컴파일을하지 않고도 구성 요소를 교체 할 수있는 시스템입니다.
    기음. 해결해야 할 여러 가지 문제가있는 경우 중요하며 일부는 엔터프라이즈 응용 프로그램에서 다루어야합니다.


통제 반전은 식료품 가게에 갈 때 당신 아내가 구입할 제품 목록을 제공 할 때입니다.

프로그래밍 용어로 콜백 함수 getProductList()를 실행중인 함수 에 전달했습니다 doShopping().

함수의 사용자가 함수의 일부분을 정의하여 더 유연하게 만들 수 있습니다.


나는 NilObject 동의하지만 다음과 같이 추가하고 싶다 :

전체 메소드를 복사하고 코드의 작은 부분 만 변경하는 경우 제어 반전으로 문제를 해결할 수 있습니다.

코드를 복사하여 붙여 넣는 것을 발견하면 거의 항상 잘못된 결과가 발생합니다. 한 번만 한 디자인 원칙으로 규정됩니다.


나는 '대조가 뒤바뀐'방식을 설명하는 아주 명확한 예를 here 에서 발견했다.

클래식 코드 (Dependency Injection없이)

DI를 사용하지 않는 코드가 대략 작동하는 방법은 다음과 같습니다.

  • 응용 프로그램에는 Foo (예 : 컨트롤러)가 필요하므로 다음을 수행하십시오.
  • 응용 프로그램이 Foo를 만듭니다.
  • 응용 프로그램 호출 Foo
    • Foo가 Bar (예 : 서비스)를 필요로하므로 다음을 수행합니다.
    • 푸가 바 생성
    • Foo는 Bar에게 전화를 겁니다.
      • Bar는 Bim (서비스, 저장소, ...)을 필요로하므로 다음을 수행합니다.
      • 바가 Bim을 만듭니다.
      • 바는 뭔가를한다.

의존성 주입 사용

DI를 사용하는 코드가 대략 작동하는 방법은 다음과 같습니다.

  • 응용 프로그램에는 Boo가 필요한 Foo가 필요합니다. Bim이 필요합니다.
  • 응용 프로그램이 Bim을 만듭니다.
  • 응용 프로그램은 Bar를 생성하고 Bim에게줍니다.
  • 응용 프로그램은 Foo를 생성하고 바를 제공합니다.
  • 응용 프로그램 호출 Foo
    • Foo는 Bar에게 전화를 겁니다.
      • 바는 뭔가를한다.

종속성의 제어는 호출되는 호출에서 호출하는 호출로 바뀝니다.

어떤 문제가 해결됩니까?

의존성 삽입은 주입 된 클래스의 다른 구현과 쉽게 교환 할 수 있습니다. 단위 테스트를 수행하는 동안 더미 구현을 주입 할 수 있으므로 테스트가 훨씬 쉬워집니다.

예 : 애플리케이션에서 사용자가 업로드 한 파일을 Google 드라이브에 저장한다고 가정합니다. DI는 컨트롤러 코드가 다음과 같이 표시 될 수 있습니다.

class SomeController
{
    private $storage;

    function __construct(StorageServiceInterface $storage)
    {
        $this->storage = $storage;
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

class GoogleDriveService implements StorageServiceInterface
{
    public function authenticate($user) {}
    public function putFile($file) {}
    public function getFile($file) {}
}

요구 사항이 변경되면 GoogleDrive 대신 Dropbox를 사용하라는 메시지가 표시됩니다. StorageServiceInterface에 대한 드롭 박스 구현 만 작성하면됩니다. Dropbox 구현이 StorageServiceInterface를 준수한다면 컨트롤러를 변경하지 않아도됩니다.

테스트하는 동안 모든 메소드가 null (또는 테스트 요구 사항에 따라 미리 정의 된 값)을 반환하는 더미 구현을 사용하여 StorageServiceInterface의 모의 객체를 만들 수 있습니다.

대신 컨트롤러 클래스에 new다음과 같은 키워드를 사용 하여 저장소 객체를 구성해야하는 경우 :

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

Dropbox 구현으로 변경하려면 newGoogleDriveService 객체가 생성 된 모든 행을 대체 하고 DropboxService를 사용해야합니다. SomeController 클래스를 테스트 할 때 생성자는 항상 GoogleDriveService 클래스를 기대하며이 클래스의 실제 메소드가 트리거됩니다.

적절한시기와 그렇지 않은 경우는 언제입니까? 제 생각에는 클래스의 대체 구현이 있다고 생각할 때 DI를 사용합니다.


Inversion of Control은 일반적인 원칙이지만 Dependency Injection은 객체 그래프 구성을위한 디자인 패턴으로이 원칙을 실현합니다. 즉, 구성은 다른 객체에 대한 참조를 얻는 방법을 제어하는 ​​객체 자체가 아니라 객체가 서로를 참조하는 방식을 제어합니다.

Inversion of Control을 디자인 패턴으로 살펴보면, 우리가 반전하고있는 것을 볼 필요가 있습니다. Dependency Injection은 객체 그래프를 생성하는 컨트롤을 반전시킵니다. 평신도의 말에 따르면 통제의 반전은 프로그램의 통제 흐름 변화를 의미한다. 예 :전통적인 독립형 응용 프로그램에서는 컨트롤이 다른 제 3 자 라이브러리로 전달되는 주요 방법 (제 3 자 라이브러리의 기능을 사용하는 경우)을 제어하지만 제어 제어의 반전을 통해 제 3 자 라이브러리 코드에서 코드로 전송됩니다 , 우리가 제 3 자 라이브러리의 서비스를받는 것처럼. 그러나 프로그램 내에서 뒤집을 필요가있는 다른 측면들 - 예를 들어 코드를 실행하기위한 메소드와 스레드의 호출 -이 있습니다.

Inversion of Control에 대한 자세한 내용은 Inversion of Control을 디자인 패턴 (OfficeFloor : 사무용 패턴을 사용하여 소프트웨어 디자인 개선 http://doi.acm.org/10.1145/2739011.2739013 무료 사본은 http://www.officefloor.net/mission.html 에서 다운로드 할 수 있음 )

식별되는 것은 다음과 같은 관계입니다 :

반전 제어 (방법) = 종속성 (상태) 주입 + 연속 주입 + 스레드 주입


아주 간단한 서면 설명은 여기에서 찾을 수 있습니다.

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

그것은 말한다

"중요하지 않은 응용 프로그램은 비즈니스 로직을 수행하기 위해 서로 협력하는 두 개 이상의 클래스로 구성됩니다. 일반적으로 각 객체는 공동 작업하는 객체 (의존성)에 대한 자체 참조를 가져 오는 역할을 담당합니다. 오브젝트는 시스템의 각 오브젝트를 조정하는 외부 엔티티에 의해 작성시 종속성이 부여됩니다. 즉, 오브젝트에 종속성이 주입됩니다. "


낚시하러 가고 싶다고 상상해 봅시다.

  • 의존성 주입 없이는 모든 것을 스스로 처리해야합니다. 보트를 찾아 낚시대를 사거나 미끼를 찾아야합니다. 물론 가능하지만 많은 책임이 있습니다. 소프트웨어 용어로,이 모든 것을 검색해야한다는 의미입니다.

  • 의존성 주입을 사용하면 다른 누군가가 모든 준비 작업을 처리하고 필요한 장비를 사용할 수 있습니다. 보트, 낚싯대 및 미끼를 사용할 준비가되어 있습니다.







oop design-patterns inversion-of-control