Ner*_*ero 91 design-patterns dependency-injection strategy-pattern
策略模式和依赖注入都允许我们在运行时设置/注入对象.策略模式和依赖注入之间有什么区别?
elj*_*nso 97
DI和策略以相同的方式工作,但策略用于更细粒度和短期的依赖关系.
当对象配置了"固定"策略时,例如在构造对象时,策略和DI之间的区别模糊.但是在DI场景中,对象的依赖关系在其生命周期中会发生变化,这种情况更为罕见,而战略并不少见.
此外,您可以将策略作为参数传递给方法,而方法参数注入的相关概念并不普遍,主要用于自动化测试的上下文中.
策略侧重于意图,并鼓励您创建具有遵循相同行为合同的不同实现的接口.DI更多的是关于实现某些行为并提供它.
使用DI,您可以出于其他原因分解您的程序,而不仅仅是为了能够交换部分实现.DI中使用的接口只有一个实现是很常见的.只有一个具体实施(永远)的"战略"不是一个真正的问题,但可能更接近DI.
tsi*_*mon 37
不同之处在于他们正在努力实现的目标.策略模式用于您知道要替换实现的情况.例如,您可能希望以不同方式格式化数据 - 您可以使用策略模式来交换XML格式化程序或CSV格式化程序等.
依赖注入的不同之处在于用户不会尝试更改运行时行为.按照上面的示例,我们可能正在创建一个使用XML格式化程序的XML导出程序.而不是像这样构造代码:
public class DataExporter() {
XMLFormatter formatter = new XMLFormatter();
}
Run Code Online (Sandbox Code Playgroud)
你会在构造函数中"注入"格式化程序:
public class DataExporter {
IFormatter formatter = null;
public DataExporter(IDataFormatter dataFormatter) {
this.formatter = dataFormatter;
}
}
DataExporter exporter = new DataExporter(new XMLFormatter());
Run Code Online (Sandbox Code Playgroud)
Dependency Injection有一些理由,但主要用于测试.您可能遇到某种类型的持久性引擎(例如数据库).但是,当您重复运行测试时,使用真实数据库可能会很麻烦.因此,对于您的测试用例,您将注入一个虚拟数据库,这样您就不会产生这种开销.
使用此示例,您可以看到不同之处:我们始终计划使用数据存储策略,它是我们传入的策略(真正的数据库实例).但是,在开发和测试中,我们希望使用不同的依赖关系,因此我们注入了不同的结构.
Jam*_*ack 27
您可以使用DI作为策略模式,因此您可以交换每个客户所需的算法,但DI可以超越它,因为它只是解耦应用程序的各个部分,这不是战略模式.
如果说DI只是一种重新命名的战略模式,那将开始削弱战略模式的真正含义,IMO将是危险的.
Jah*_*ine 13
Dude,依赖注入是一种更普遍的模式,它是关于抽象的依赖而不是具体结构,它是每个模式的一部分,但战略模式是更具体问题的解决方案
这是维基百科的定义:
DI:
面向对象计算机编程中的依赖注入(DI)是一种设计模式,其核心原则是将行为与依赖性解析分离.换句话说:用于解耦高度依赖的软件组件的技术.
策略模式:
在计算机编程中,策略模式(也称为策略模式)是特定的软件设计模式,由此可以在运行时选择算法.
策略模式旨在提供定义算法族的方法,将每个算法封装为对象,并使它们可互换.策略模式允许算法独立于使用它们的客户端.
小智 7
策略是用于改变事物计算方式的更高级别的事物.使用依赖注入,您不仅可以更改事物的计算方式,还可以更改其中的内容.
对我来说,使用单元测试时会很清楚.对于生产代码执行,您隐藏了所有数据(即私有或受保护); 然而,通过单元测试,大多数数据都是公开的,所以我可以用Asserts查看它.
策略示例:
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 (...);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,策略之间没有不同的公共数据.也没有任何不同的方法.两种策略共享所有相同的功能和签名.
现在为依赖注入:
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 (...);
}
}
Run Code Online (Sandbox Code Playgroud)
使用:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
注意最后2个检查.他们使用注入被测试类的测试双重中的公共数据.由于数据隐藏原则,我无法使用生产代码执行此操作.我不想在生产代码中插入专用测试代码.公共数据必须属于不同的类别.
注射试验双.这不仅仅是一种策略,因为它影响数据而不仅仅是功能.