[design-patterns] 의존성 주입이란 무엇입니까?



14 Answers

지금까지 발견 한 최고의 정의는 James Shore의 것입니다 .

"의존성 주입"은 5 센트 개념의 25 달러 용어입니다. [...] 의존성 주입이란 객체에 인스턴스 변수를주는 것을 의미합니다. [...].

마틴 파울러 (Martin Fowler ) 의 기사 또한 유용 할 수 있습니다.

의존성 주입은 기본적으로 객체가 필요로하는 객체 (의존성)를 객체 자체로 생성하는 대신에 제공합니다. 의존성을 조롱하거나 스터브 아웃 (stubbed) 할 수 있으므로 테스트에 매우 유용한 기술입니다.

의존성은 여러 가지 방법 (생성자 삽입 또는 설정자 삽입 등)을 통해 객체에 주입 할 수 있습니다. 하나의 특수 종속성 주입 프레임 워크 (예 : Spring)를 사용하여이를 수행 할 수도 있지만 반드시 필요하지는 않습니다. 이러한 프레임 워크에 종속성 주입이 필요하지 않습니다. 객체 (의존성)를 명시 적으로 인스턴스화하고 전달하는 것은 프레임 워크에 의한 주입만큼 좋은 주입입니다.

Question

종속성 삽입 에 대한 특정 질문과 함께 게시 할 몇 가지 질문이 있습니다. 예를 들어 언제 사용하고 프레임 워크에 어떤 질문이 있습니까? 하나,

의존성 주입이란 무엇이며, 언제 / 왜 사용해야합니까, 사용하지 않아야합니까?







DI (Dependency Injection) 란 무엇입니까?

다른 사람들이 말했듯이, DI (Dependency Injection) 는 우리의 관심 대상 (소비자 계층)이 ( UML 관점에서 ) 종속되어있는 다른 객체 인스턴스의 직접 작성 및 수명 관리의 책임을 제거합니다. 대신 이러한 인스턴스는 일반적으로 생성자 매개 변수 또는 속성 설정자를 통해 소비자 클래스에 전달됩니다 (종속 클래스 인스턴스의 관리 및 소비자 클래스 전달은 대개 Inversion of Control (IoC) 컨테이너에서 수행되지만 다른 주제입니다) .

DI, DIP 및 SOLID

특히 로버트 C 마틴 (Robert C Martin)의 객체 지향 설계 (Object Oriented Design)SOLID 원칙의 패러다임에서 DI의존성 반전 원리 (Dependency Inversion Principle, DIP) 의 가능한 구현 중 하나이다. DIP은 SOLID mantra의 D 입니다. 다른 DIP 구현에는 Service Locator 및 Plugin 패턴이 포함됩니다.

DIP의 목적은 클래스 간의 긴밀하고 구체적인 의존 관계를 분리하고, 사용 된 언어와 접근 방식에 따라 interface , abstract class 또는 pure virtual class 를 통해 구현할 수있는 추상화를 통해 커플 링을 느슨하게하는 것입니다 .

DIP이 없으면 우리의 코드 (이 '소비 클래스'라고 불렀습니다)는 구체적인 종속성과 직접적으로 관련되어 있으며, 종종 이러한 종속성의 인스턴스를 얻고 관리하는 방법을 아는 책임이 있습니다 (즉, 개념적으로).

"I need to create/use a Foo and invoke method `GetBar()`"

DIP를 적용한 후에 요구 사항이 느슨해지고 Foo 의존성의 수명을 얻고 관리하는 것에 대한 우려가 제거되었습니다.

"I need to invoke something which offers `GetBar()`"

DIP (및 DI)를 사용해야하는 이유는 무엇입니까?

이러한 방식으로 클래스 간의 종속성을 분리하면 이러한 종속성 클래스를 추상화의 전제 조건을 충족하는 다른 구현으로 쉽게 대체 할 수 있습니다 (예 : 종속성을 동일한 인터페이스의 다른 구현으로 전환 할 수 있음). 게다가 다른 사람들이 언급했듯이, 아마도 DIP를 통해 클래스들을 분리 하는 가장 일반적인 이유는 소비 클래스가 고립되어 테스트되도록 허용하는 것입니다. 왜냐하면이 같은 의존성이 이제는 스텁 및 / 또는 조롱 될 수 있기 때문입니다.

DI의 한 가지 결과는 종속성 객체가 생성자 또는 설정자 주입을 통해 소비 클래스로 전달되므로 종속 객체 인스턴스의 수명 관리가 더 이상 소비 클래스에 의해 제어되지 않는다는 것입니다.

다른 방법으로 볼 수 있습니다.

  • 소비 클래스에 의한 종속성의 수명 제어가 유지되어야하는 경우, 종속 클래스 인스턴스를 생성하기위한 (추상) 팩토리를 소비자 클래스에 주입하여 제어를 다시 설정할 수 있습니다. 소비자는 필요에 따라 공장에서 Create 를 통해 인스턴스를 얻을 수 있으며 완료되면 이러한 인스턴스를 처분 할 수 있습니다.
  • 또는 종속 인스턴스의 수명 제어를 IoC 컨테이너에 맡길 수 있습니다 (자세한 내용은 아래 참조).

DI를 언제 사용합니까?

  • 동등한 구현을 위해 의존성을 대체 할 필요가있을 경우,
  • 의존성을 분리하여 클래스의 메소드를 단위 테스트해야하는 경우 언제든지,
  • 의존성 수명의 불확실성이 실험을 보증 할 수있는 곳에서 (예, MyDepClass , MyDepClass 는 스레드 안전합니다 - 우리가 싱글 톤으로 만들고 모든 인스턴스에 동일한 인스턴스를 삽입한다면 어떨까요?)

다음은 간단한 C # 구현입니다. 주어진 소비 클래스 :

public class MyLogger
{
   public void LogRecord(string somethingToLog)
   {
      Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
   }
}

겉으로보기에는 무해하지만, System.DateTimeSystem.Console 이라는 두 가지 클래스에 static 종속성이 두 가지 있습니다.이 클래스는 로깅 출력 옵션을 제한하지 않으며 (아무도보고 있지 않으면 콘솔 로깅은 쓸모가 없습니다.) 더 나쁘고 어렵습니다. 비 결정적 시스템 클럭에 대한 종속성을 자동으로 테스트합니다.

우리는이 클래스에 DIP 을 적용 할 수 있습니다. 타임 스탬프의 관심을 종속성으로 추상화하고 MyLogger 를 간단한 인터페이스에만 연결 MyLogger 됩니다.

public interface IClock
{
    DateTime Now { get; }
}

또한 Console 에 대한 종속성을 TextWriter 와 같은 추상화로 완화 할 수 있습니다. Dependency Injection은 일반적으로 constructor 삽입 (소비 클래스의 생성자에 대한 매개 변수로 추상화를 종속으로 전달) 또는 Setter Injection ( setXyz() setter 또는 .Net Property를 통해 종속성 전달)로 setXyz() {set;} 한정된). 생성자 삽입은 클래스가 생성 된 후에 올바른 상태가되고 내부 종속성 필드가 readonly (C #) 또는 final (Java)으로 표시 될 수 있으므로 바람직합니다. 위 예제에서 생성자 삽입을 사용하면 다음과 같은 결과가 나옵니다.

public class MyLogger : ILogger // Others will depend on our logger.
{
    private readonly TextWriter _output;
    private readonly IClock _clock;

    // Dependencies are injected through the constructor
    public MyLogger(TextWriter stream, IClock clock)
    {
        _output = stream;
        _clock = clock;
    }

    public void LogRecord(string somethingToLog)
    {
        // We can now use our dependencies through the abstraction 
        // and without knowledge of the lifespans of the dependencies
        _output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog);
    }
}

(콘크리트 Clock 를 제공해야하며 당연히 DateTime.Now 되돌아 갈 수 있으며 두 종속성은 생성자 주입을 통해 IoC 컨테이너에서 제공해야합니다)

자동화 된 유닛 테스트를 빌드 할 수 있습니다.이 테스트는 로거가 올바르게 작동하고 있음을 증명합니다. 이제는 종속성에 대한 제어권을 갖게되었습니다. 시간이 지나면 서면 출력을 감시 할 수 있습니다.

[Test]
public void LoggingMustRecordAllInformationAndStampTheTime()
{
    // Arrange
    var mockClock = new Mock<IClock>();
    mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45));
    var fakeConsole = new StringWriter();

    // Act
    new MyLogger(fakeConsole, mockClock.Object)
        .LogRecord("Foo");

    // Assert
    Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString());
}

다음 단계

종속성 삽입은 항상 Inversion of Control 컨테이너 (IoC) 와 연관되어 있으며, 구체적인 종속 인스턴스를 주입 (제공)하고 수명 인스턴스를 관리합니다. 구성 / 부트 스트랩 프로세스 중에 IoC 컨테이너는 다음을 정의 할 수 있습니다.

  • 각 추상화와 구성된 구체화 구현 간의 매핑 (예 : "소비자가 IBar 요청하고 ConcreteBar 인스턴스를 반환 할 때" )
  • 각 소비자 인스턴스에 대해 새로운 객체를 생성하고, 모든 소비자에 대해 단일 종속성 인스턴스를 공유하고, 동일한 스레드에서만 동일한 종속성 인스턴스를 공유하는 등의 각 종속성의 수명 관리를위한 정책을 설정할 수 있습니다.
  • .Net에서 IoC 컨테이너는 IDisposable 과 같은 프로토콜을 인식하고 구성된 수명 관리에 따라 종속성 삭제의 책임을 맡습니다.

일반적으로 IoC 컨테이너가 구성되고 / 부트 스트랩 된 후에는 백그라운드에서 원활하게 작동하여 코더가 의존성에 대해 걱정하지 않고 직접 코드에 집중할 수있게합니다.

DI 친화적 인 코드의 핵심은 클래스의 정적 결합을 방지하고 종속성 생성을 위해 new ()를 사용하지 않는 것입니다.

위의 예에서와 같이 종속성을 분리하려면 일부 디자인 작업이 필요하며 개발자에게는 new 종속성 습관을 직접적으로 파기하고 종속성을 관리하기 위해 컨테이너를 신뢰하는 패러다임 전환이 필요합니다.

그러나 혜택은 많은 것이고 특히 관심 분야를 철저히 테스트 할 수있는 능력에 있습니다.

참고 : POCO / POJO / 직렬화 DTO / 엔티티 그래프 / 익명의 JSON 투영법 (예 : "데이터 만"클래스 또는 레코드)의 생성 / 매핑 / 투영 ( new ..() 를 통해) 메소드에서 사용되거나 리턴 된 메소드는 간주 되지 않습니다 (UML의 의미에서) 종속성으로 간주되며 DI가 적용되지 않습니다. new 프로젝트를 사용하면 이것만으로도 좋습니다.




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

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

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




The best analogy I can think of is the surgeon and his assistant(s) in an operation theater, where the surgeon is the main person and his assistant who provides the various surgical components when he needs it so that the surgeon can concentrate on the one thing he does best (surgery). Without the assistant the surgeon has to get the components himself every time he needs one.

DI for short, is a technique to remove a common additional responsibility (burden) on components to fetch the dependent components, by providing them to it.

DI brings you closer to the Single Responsibility (SR) principle, like the surgeon who can concentrate on surgery .

When to use DI : I would recommend using DI in almost all production projects ( small/big), particularly in ever changing business environments :)

Why : Because you want your code to be easily testable, mockable etc so that you can quickly test your changes and push it to the market. Besides why would you not when you there are lots of awesome free tools/frameworks to support you in your journey to a codebase where you have more control.




Car 클래스와 Engine 클래스로 간단한 예제를 시도해 봅시다. 어떤 자동차라도 적어도 현재는 어디든 갈 엔진이 필요합니다. 종속성 주입없이 코드가 어떻게 보이는지 아래에 있습니다.

public class Car
{
    public Car()
    {
        GasEngine engine = new GasEngine();
        engine.Start();
    }
}

public class GasEngine
{
    public void Start()
    {
        Console.WriteLine("I use gas as my fuel!");
    }
}

Car 클래스를 인스턴스화하기 위해 다음 코드를 사용합니다.

Car car = new Car();

우리가 GasEngine과 긴밀하게 결합한이 코드의 문제점과 우리가 ElectricEngine으로 변경하기로 결정하면 Car 클래스를 다시 작성해야합니다. 그리고 응용 프로그램이 커질수록 새로운 유형의 엔진을 추가하고 사용해야하는 문제와 두통이 생깁니다.

즉,이 접근법은 우리의 상위 수준의 Car 클래스가 SOLID의 Dependency Inversion Principle (DIP)을 위반하는 하위 수준의 GasEngine 클래스에 종속된다는 것입니다. DIP는 우리가 구체적인 클래스가 아닌 추상화에 의존해야한다고 제안합니다. 그래서 이것을 만족시키기 위해 IEngine 인터페이스를 소개하고 아래와 같이 코드를 다시 작성합니다 :

    public interface IEngine
    {
        void Start();
    }

    public class GasEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I use gas as my fuel!");
        }
    }

    public class ElectricityEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I am electrocar");
        }
    }

    public class Car
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)
        {
            _engine = engine;
        }

        public void Run()
        {
            _engine.Start();
        }
    }

이제 Car 클래스는 엔진의 특정 구현이 아닌 IEngine 인터페이스에만 의존합니다. 자, 유일한 트릭은 우리가 어떻게 자동차의 인스턴스를 생성하고 GasEngine 또는 ElectricityEngine과 같은 실제적인 구체적인 Engine 클래스를 제공 할 것인가입니다. 그것이 의존성 주입 이 들어오는 곳입니다.

   Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

여기서 우리는 기본적으로 자동차 생성자에 의존성 (엔진 인스턴스)을 주입 (전달)합니다. 이제 우리 클래스는 객체와 그 의존성 사이의 느슨한 결합을 가지며 Car 클래스를 변경하지 않고도 새로운 유형의 엔진을 쉽게 추가 할 수 있습니다.

클래스가 하드 코딩 된 종속성이 없으므로 클래스가 더 느슨하게 결합 된 종속성 삽입 의 주요 이점. 이것은 위에서 언급 한 종속성 반전 원칙을 따릅니다. 특정 구현을 참조하는 대신 클래스는 클래스가 생성 될 때 제공되는 추상화 (일반적으로 인터페이스 )를 요청합니다.

그래서 결국에는 의존성 주입 은 객체와 의존성 사이의 느슨한 결합을 달성하기위한 기술 일 뿐이다. 그 동작을 수행하기 위해 클래스가 필요로하는 의존성을 직접 인스턴스화하는 대신 생성자 주입을 통해 클래스에 의존성을 제공합니다 (대부분).

또한 우리가 많은 의존성을 가지고있는 경우 Inversion of Control (IoC) 컨테이너를 사용하는 것이 좋습니다. 우리는 어떤 인터페이스가 모든 의존성에 대한 어떤 구체적인 구현으로 매핑되어야 하는지를 알 수 있으며, 우리가 구성 할 때 우리가 그 의존성을 해결할 수 있습니다 우리의 목표. 예를 들어, IoC 컨테이너에 대한 매핑에서 IEngine 종속성을 GasEngine 클래스에 매핑해야한다고 지정할 수 있으며 IoC 컨테이너에 Car 클래스의 인스턴스를 요청하면 GasEngine 종속성을 사용하여 Car 클래스를 자동으로 구성합니다 통과했다.

UPDATE : Julie Lerman의 EF Core에 관한 과정을 최근에 보았고 또한 DI에 관한 그녀의 짧은 정의가 마음에 들었습니다.

Dependency Injection은 애플리케이션이 클래스를 필요로하는 클래스에 즉각적으로 삽입 할 수있게 해주는 패턴이다. 이를 통해 코드를 좀 더 느슨하게 결합 할 수 있으며 Entity Framework Core는이 동일한 서비스 시스템에 연결됩니다.




The whole point of Dependency Injection (DI) is to keep application source code clean and stable :

  • clean of dependency initialization code
  • stable regardless of dependency used

Practically, every design pattern separates concerns to make future changes affect minimum files.

The specific domain of DI is delegation of dependency configuration and initialization.

Example: DI with shell script

If you occasionally work outside of Java, recall how source is often used in many scripting languages (Shell, Tcl, etc., or even import in Python misused for this purpose).

Consider simple dependent.sh script:

#!/bin/sh
# Dependent
touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

The script is dependent: it won't execute successfully on its own ( archive_files is not defined).

You define archive_files in archive_files_zip.sh implementation script (using zip in this case):

#!/bin/sh
# Dependency
function archive_files {
    zip files.zip "$@"
}

Instead of source -ing implementation script directly in the dependent one, you use an injector.sh "container" which wraps both "components":

#!/bin/sh 
# Injector
source ./archive_files_zip.sh
source ./dependent.sh

The archive_files dependency has just been injected into dependent script.

You could have injected dependency which implements archive_files using tar or xz .

Example: removing DI

If dependent.sh script used dependencies directly, the approach would be called dependency lookup (which is opposite to dependency injection ):

#!/bin/sh
# Dependent

# dependency look-up
source ./archive_files_zip.sh

touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

Now the problem is that dependent "component" has to perform initialization itself.

The "component"'s source code is neither clean nor stable because every changes in initialization of dependencies requires new release for "components"'s source code file as well.

Last words

DI is not as largely emphasized and popularized as in Java frameworks.

But it's a generic approach to split concerns of:

  • application development ( single source code release lifecycle)
  • application deployment ( multiple target environments with independent lifecycles)

Using configuration only with dependency lookup does not help as number of configuration parameters may change per dependency (eg new authentication type) as well as number of supported types of dependencies (eg new database type).




Any nontrivial application is made up of two or more classes that collaborate with each other to perform some business logic. Traditionally, each object is responsible for obtaining its own references to the objects it collaborates with (its dependencies). When applying DI, the objects are given their dependencies at creation time by some external entity that coordinates each object in the system. In other words, dependencies are injected into objects.

For further details please see enter link description here




I think since everyone has written for DI, let me ask a few questions..

  1. When you have a configuration of DI where all the actual implementations(not interfaces) that are going to be injected into a class (for eg services to a controller) why is that not some sort of hard-coding?
  2. What if I want to change the object at runtime? For example, my config already says when I instantiate MyController, inject for FileLogger as ILogger. But I might want to inject DatabaseLogger.
  3. Everytime I want to change what objects my AClass needs, I need to now look into two places - The class itself and the configuration file. How does that make life easier?
  4. If Aproperty of AClass is not injected, is it harder to mock it out?
  5. Going back to the first question. If using new object() is bad, how come we inject the implementation and not the interface? I think a lot of you are saying we're in fact injecting the interface but the configuration makes you specify the implementation of that interface ..not at runtime .. it is hardcoded during compile time.

This is based on the answer @Adam N posted.

Why does PersonService no longer have to worry about GroupMembershipService? You just mentioned GroupMembership has multiple things(objects/properties) it depends on. If GMService was required in PService, you'd have it as a property. You can mock that out regardless of whether you injected it or not. The only time I'd like it to be injected is if GMService had more specific child classes, which you wouldn't know until runtime. Then you'd want to inject the subclass. Or if you wanted to use that as either singleton or prototype. To be honest, the configuration file has everything hardcoded as far as what subclass for a type (interface) it is going to inject during compile time.

편집하다

A nice comment by Jose Maria Arranz on DI

DI increases cohesion by removing any need to determine the direction of dependency and write any glue code.

False. The direction of dependencies is in XML form or as annotations, your dependencies are written as XML code and annotations. XML and annotations ARE source code.

DI reduces coupling by making all of your components modular (ie replacable) and have well-defined interfaces to each other.

False. You do not need a DI framework to build a modular code based on interfaces.

About replaceable: with a very simple .properties archive and Class.forName you can define wich classes can change. If ANY class of your code can be changed, Java is not for you, use an scripting language. By the way: annotations cannot be changed without recompiling.

In my opinion there is one only reason for DI frameworks: boiler plate reduction. With a well done factory system you can do the same, more controlled and more predictable as your preferred DI framework, DI frameworks promise code reduction (XML and annotations are source code too). The problem is this boiler plate reduction is just real in very very simple cases (one instance-per class and similar), sometimes in the real world picking the appropriated service object is not as easy as mapping a class to a singleton object.




Dependency Injection means a way (actually any-way ) for one part of code (eg a class) to have access to dependencies (other parts of code, eg other classes, it depends upon) in a modular way without them being hardcoded (so they can change or be overriden freely, or even be loaded at another time, as needed)

(and ps , yes it has become an overly-hyped 25$ name for a rather simple, concept) , my .25 cents




The popular answers are unhelpful, because they define dependency injection in a way that isn't useful. Let's agree that by "dependency" we mean some pre-existing other object that our object X needs. But we don't say we're doing "dependency injection" when we say

$foo = Foo->new($bar);

We just call that passing parameters into the constructor. We've been doing that regularly ever since constructors were invented.

"Dependency injection" is considered a type of "inversion of control", which means that some logic is taken out of the caller. That isn't the case when the caller passes in parameters, so if that were DI, DI would not imply inversion of control.

DI means there is an intermediate level between the caller and the constructor which manages dependencies. A Makefile is a simple example of dependency injection. The "caller" is the person typing "make bar" on the command line, and the "constructor" is the compiler. The Makefile specifies that bar depends on foo, and it does a

gcc -c foo.cpp; gcc -c bar.cpp

before doing a

gcc foo.o bar.o -o bar

The person typing "make bar" doesn't need to know that bar depends on foo. The dependency was injected between "make bar" and gcc.

The main purpose of the intermediate level is not just to pass in the dependencies to the constructor, but to list all the dependencies in just one place , and to hide them from the coder (not to make the coder provide them).

Usually the intermediate level provides factories for the constructed objects, which must provide a role that each requested object type must satisfy. That's because by having an intermediate level that hides the details of construction, you've already incurred the abstraction penalty imposed by factories, so you might as well use factories.




from Book Apress.Spring.Persistence.with.Hibernate.Oct.2010

The purpose of dependency injection is to decouple the work of resolving external software components from your application business logic.Without dependency injection, the details of how a component accesses required services can get muddled in with the component's code. This not only increases the potential for errors, adds code bloat, and magnifies maintenance complexities; it couples components together more closely, making it difficult to modify dependencies when refactoring or testing.




Dependency Injection is a type of implementation of the " Inversion of Control " principle on which is based Frameworks building.

Frameworks as stated in "Design Pattern" of GoF are classes that implement the main control flow logic raising the developer to do that, in this way Frameworks realize the inversion of control principle.

A way to implement as a technique, and not as class hierarchy, this IoC principle it is just Dependency Injection.

DI consists mainly into delegate the mapping of classes instances and type reference to that instances, to an external "entity": an object, static class, component, framework, etc...

Classes instances are the " dependencies ", the external binding of the calling component with the class instance through the reference it is the " injection ".

Obviously you can implement this technique in many way as you want from OOP point of view, see for example constructor injection , setter injection , interface injection .

Delegating a third party to carry out the task of match a ref to an object it is very useful when you want to completely separate a component that needs some services from the same services implementation.

In this way, when designing components, you can focus exclusively on their architecture and their specific logic, trusting on interfaces for collaborating with other objects without worry about any type of implementation changes of objects/services used, also if the same object you are using will be totally replaced (obviously respecting the interface).




Dependency injection is the heart of the concept related with Spring Framework.While creating the framework of any project spring may perform a vital role,and here dependency injection come in pitcher.

Actually,Suppose in java you created two different classes as class A and class B, and whatever the function are available in class B you want to use in class A, So at that time dependency injection can be used. where you can crate object of one class in other,in the same way you can inject an entire class in another class to make it accessible. by this way dependency can be overcome.

DEPENDENCY INJECTION IS SIMPLY GLUING TWO CLASSES AND AT THE SAME TIME KEEPING THEM SEPARATE.




Dependency Injection은 내부적으로 구성하는 대신 다른 코드 조각에서 개체의 인스턴스를받는 방식으로 개체를 디자인하는 방식입니다. 즉, 객체가 필요로하는 인터페이스를 구현하는 객체는 코드를 변경하지 않고 대체 할 수 있으므로 테스트가 간단 해지고 디커플링이 향상됩니다.

예를 들어, 다음과 같은 클립을 고려하십시오.

public class PersonService {
  public void addManager( Person employee, Person newManager ) { ... }
  public void removeManager( Person employee, Person oldManager ) { ... }
  public Group getGroupByManager( Person manager ) { ... }
}

public class GroupMembershipService() {
  public void addPersonToGroup( Person person, Group group ) { ... }
  public void removePersonFromGroup( Person person, Group group ) { ... }
} 

이 예제에서, PersonService::addManagerPersonService::addManager PersonService::removeManager 의 구현은 GroupMembershipService 인스턴스가 필요하다. Dependency Injection이 없다면 GroupMembershipService 의 생성자에서 새로운 GroupMembershipService 를 인스턴스화하고 두 인스턴스에서 그 인스턴스 속성을 사용하는 것이 전통적인 방법 일 것이다. 그러나 GroupMembershipService 의 생성자에 여러 가지가 필요한 경우 또는 더 나쁜 경우에는 GroupMembershipService 에서 호출해야하는 초기화 "설정자"가 있고 코드가 빠르게 커지고 PersonService 이제 GroupMembershipService 뿐 아니라 GroupMembershipService 의존하는 다른 모든 것. 또한 GroupMembershipService 대한 연결은 GroupMembershipService 에 하드 코드되어 있습니다. 즉, 테스트 용도로 GroupMembershipService 를 "더미"하거나 응용 프로그램의 다른 부분에서 전략 패턴을 사용할 수 없다는 것을 의미합니다.

Dependency Injection을 사용하면 GroupMembershipService 에서 GroupMembershipService 를 인스턴스화하는 대신 PersonService 생성자에 전달하거나 Property (getter 및 setter)를 추가하여 PersonService 인스턴스의 로컬 인스턴스를 설정할 수 있습니다. 즉, PersonService 는 더 이상 GroupMembershipService 를 작성하는 방법에 대해 걱정할 필요가 없으며 주어진 GroupMembershipService 를 승인하고이를 사용하여 작업합니다. 이는 또한 GroupMembershipService 의 서브 클래스이거나 GroupMembershipService 인터페이스를 구현하는 것이 GroupMembershipService "주입"될 수 있으며 PersonService 는 변경 사항을 알 필요가 없음을 의미합니다.






Related