전략 패턴과 종속성 주입의 차이점은 무엇입니까?
전략 패턴과 의존성 주입은 모두 런타임에 객체를 설정 / 주입 할 수있게합니다. 전략 패턴과 종속성 주입의 차이점은 무엇입니까?
DI와 Strategy는 같은 방식으로 작동하지만 Strategy는 더 세분화되고 수명이 짧은 종속성에 사용됩니다.
개체가 "고정 된"전략으로 구성되면 (예 : 개체가 구성 될 때) 전략과 DI의 구분이 흐려집니다. 그러나 DI 시나리오에서는 객체의 종속성이 수명 동안 변경되는 것이 더 드물지만 전략에서는 드물지 않습니다.
또한 전략을 메서드에 인수로 전달할 수 있지만 메서드 인수 주입의 관련 개념은 널리 퍼져 있지 않으며 대부분 자동화 된 테스트의 컨텍스트에서만 사용됩니다.
전략은 의도에 초점을 맞추고 동일한 행동 계약을 따르는 다른 구현으로 인터페이스를 만들도록 권장합니다. DI는 단지 일부 동작을 구현하고 제공하는 것에 관한 것입니다.
DI를 사용하면 구현의 일부를 교체 할 수있는 것 이외의 다른 이유로 프로그램을 분해 할 수 있습니다. 하나의 구현만으로 DI에서 사용되는 인터페이스는 매우 일반적입니다. 구체적인 구현이 하나 뿐인 "전략"은 실제 문제는 아니지만 DI에 더 가깝습니다.
차이점은 그들이 달성하려는 것입니다. 전략 패턴은 구현을 교체하려는 상황에서 사용됩니다. 예를 들어 다양한 방식으로 데이터를 포맷 할 수 있습니다. 전략 패턴을 사용하여 XML 포맷터 또는 CSV 포맷터 등을 교체 할 수 있습니다.
종속성 주입은 사용자가 런타임 동작을 변경하려고하지 않는다는 점에서 다릅니다. 위의 예에 따라 XML 포맷터를 사용하는 XML 내보내기 프로그램을 만들 수 있습니다. 다음과 같이 코드를 구성하는 대신 :
public class DataExporter() {
XMLFormatter formatter = new XMLFormatter();
}
생성자에 포맷터를 '주입'합니다.
public class DataExporter {
IFormatter formatter = null;
public DataExporter(IDataFormatter dataFormatter) {
this.formatter = dataFormatter;
}
}
DataExporter exporter = new DataExporter(new XMLFormatter());
의존성 주입에 대한 몇 가지 타당성이 있지만 기본은 테스트를위한 것입니다. 일종의 지속성 엔진 (예 : 데이터베이스)이있는 경우가있을 수 있습니다. 그러나 테스트를 반복적으로 실행할 때 실제 데이터베이스를 사용하는 것은 고통 스러울 수 있습니다. 따라서 테스트 케이스의 경우 더미 데이터베이스를 삽입하여 오버 헤드가 발생하지 않도록합니다.
이 예제를 사용하면 차이점을 확인할 수 있습니다. 우리는 항상 데이터 스토리지 전략을 사용할 계획이며 전달하는 전략입니다 (실제 DB 인스턴스). 그러나 개발 및 테스트에서는 서로 다른 종속성을 사용하기를 원하므로 다른 결론을 주입합니다.
DI를 전략 패턴으로 사용할 수 있으므로 각 고객에게 필요한 알고리즘을 바꿀 수 있지만 DI는 응용 프로그램의 일부가 아닌 부분을 분리하는 방법이므로이를 넘어 설 수 있습니다. 전략 패턴.
DI가 IMO라는 전략 패턴의 진정한 의미를 희석시키기 시작하기 때문에 DI가 단지 이름이 바뀐 전략 패턴이라고 말하는 것은 위험 할 것입니다.
야, 의존성 주입은 더 일반적인 패턴이고, 그것은 구체화가 아닌 추상화에 대한 의존성에 관한 것이며 모든 패턴의 일부이지만 전략 패턴은 더 구체적인 문제에 대한 해결책입니다.
이것은 wikipedia의 정의입니다.
DI :
객체 지향 컴퓨터 프로그래밍의 DI (Dependency Injection)는 동작을 종속성 해결과 분리하는 핵심 원칙이있는 디자인 패턴입니다. 즉, 고도로 종속 된 소프트웨어 구성 요소를 분리하는 기술입니다.
전략 패턴 :
컴퓨터 프로그래밍에서 전략 패턴 (정책 패턴이라고도 함)은 런타임에 알고리즘을 선택할 수있는 특정 소프트웨어 디자인 패턴입니다.
전략 패턴은 알고리즘 패밀리를 정의하고 각 알고리즘을 객체로 캡슐화하고 상호 교환 가능하게 만드는 수단을 제공하기위한 것입니다. 전략 패턴을 사용하면 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있습니다.
전략은 사물이 계산되는 방식을 변경하는 데 사용되는 상위 수준의 사물입니다. 의존성 주입을 사용하면 계산 방법뿐만 아니라 거기에있는 내용도 변경할 수 있습니다.
저에게는 단위 테스트를 사용할 때 명확 해집니다. 프로덕션 코드 실행을 위해 모든 데이터가 숨겨져 있습니다 (예 : 비공개 또는 보호됨). 반면 단위 테스트에서는 대부분의 데이터가 공개되어 있으므로 Assert로 볼 수 있습니다.
전략의 예 :
public class Cosine {
private CalcStrategy strat;
// Constructor - strategy passed in as a type of DI
public Cosine(CalcStrategy s) {
strat = s;
}
}
public abstract class CalcStrategy {
public double goFigure(double angle);
}
public class RadianStrategy extends CalcStrategy {
public double goFigure(double angle) {
return (...);
}
}
public class DegreeStrategy extends CalcStrategy {
public double goFigure(double angle) {
return (...);
}
}
전략간에 다른 공개 데이터는 없습니다. 다른 방법도 없습니다. 두 전략 모두 동일한 기능과 서명을 공유합니다.
Now for the dependency injection:
public class Cosine {
private Calc strat;
// Constructor - Dependency Injection.
public Cosine(Calc s) {
strat = s;
}
}
public class Calc {
private int numPasses = 0;
private double total = 0;
private double intermediate = 0;
public double goFigure(double angle) {
return(...);
}
public class CalcTestDouble extends Calc {
// NOTICE THE PUBLIC DATA.
public int numPasses = 0;
public double total = 0;
public double intermediate = 0;
public double goFigure(double angle) {
return (...);
}
}
Use:
public CosineTest {
@Test
public void testGoFigure() {
// Setup
CalcTestDouble calc = new CalcTestDouble();
Cosine instance = new Cosine(calc);
// Exercise
double actualAnswer = instance.goFigure(0.0);
// Verify
double tolerance = ...;
double expectedAnswer = ...;
assertEquals("GoFigure didn't work!", expectedAnswer,
actualAnswer, tolerance);
int expectedNumPasses = ...;
assertEquals("GoFigure had wrong number passes!",
expectedNumPasses, calc.numPasses);
double expectedIntermediate = ...;
assertEquals("GoFigure had wrong intermediate values!",
expectedIntermediate, calc.intermediate, tolerance);
}
}
Notice the last 2 checks. They used the public data in the test double that was injected into the class under test. I couldn't do this with production code because of the data hiding principle. I didn't want to have special purpose testing code inserted in the production code. The public data had to be in a different class.
The test double was injected. That is different than just a strategy since it affected data and not just functions.
Dependency injection is a refinement of the strategy pattern which I will briefly explain. It is often necessary to choose between several alternative modules at runtime. These modules all implement a common interface so that they can be used interchangeably. The purpose of the strategy pattern is to remove the burden of deciding upon which of the modules to use (ie which "concrete strategy" or dependency) by encapsulating the decision-making process into a separate object which I will call the strategy object.
Dependency injection refines the strategy pattern by not only deciding which concrete strategy to use but creating an instance of the concrete strategy and "injecting" it back into the calling module. This is useful even if there is only a single dependency as the knowledge of how to manage (initialise etc) the concrete strategy instance can also be hidden within the strategy object.
Actually, dependency injection also looks very similar to the Bridge pattern. To me (and according to the definition), the Bridge pattern is to accommodate different versions of the implementation, while the Strategy pattern is for the totally different logic. But the sample code looks like it's using DI. So maybe DI is just a technic or implementation?
Strategy is an arena to use your dependency injection skills. Real ways to implement dependency injection are as follows:-
- Events
- Configuration files of unity/structure map(or programmatically) etc.
- Extension Methods
- Abstract Factory pattern
- Inversion of control pattern(used by both strategy and Abstract Factory)
There is one thing though that makes strategy stands apart. As you know in Unity when the application starts up all dependencies are set and we can't change it further. But strategy supports runtime dependency change. But WE have to manage/inject the dependency, not the responsibility of Strategy!
Actually strategy does not talk about dependency injection. If needed it can be done through Abstract Factory inside a Strategy pattern. Strategy only talks about creating a family of classes with interface and 'playing' with it. While playing, if we find the classes are in a different tier then we have to inject it ourselves but not the job of Strategy.
If we consider SOLID principles - We use Strategy Pattern for Open Closed Principle and Dependency Injection for Dependency Inversion Principle
'programing' 카테고리의 다른 글
tomcat-CATALINA_BASE 및 CATALINA_HOME 변수 (0) | 2020.09.05 |
---|---|
Java 애플리케이션을 다시 시작하려면 어떻게해야합니까? (0) | 2020.09.05 |
두 개의 int를 나누면 double에 할당 될 때 올바른 값이 생성되지 않는 이유는 무엇입니까? (0) | 2020.09.05 |
Log4Net, 내 로깅에 사용자 정의 필드를 추가하는 방법 (0) | 2020.09.05 |
Bootstrap에서 토글 버튼을 만드는 방법 (0) | 2020.09.05 |