1 回答
TA贡献1799条经验 获得超6个赞
在使用依赖注入时,抽象工厂模式经常被过度使用。这并不意味着它本身就是一个糟糕的模式,但在许多情况下,抽象工厂模式有更合适的替代方案。这在依赖注入原则、实践和模式(第6.2段)中有详细描述,其中描述:
不应该使用抽象工厂来创建短期的、有状态的依赖项,因为依赖项的使用者应该无视它的生命周期;从消费者的角度来看,概念上应该只有一个服务实例。
抽象工厂通常违反依赖倒置原则 (DIP),因为它们的设计通常不适合消费者,而 DIP 声明:“抽象由上层/策略层拥有”,这意味着抽象的消费者应该决定其以最适合其需求的方式塑造和定义抽象。让消费者同时依赖工厂依赖和它产生的依赖会使消费者变得复杂。
这意味着:
Abstract 应避免使用无参数 create 方法的工厂,因为这意味着依赖项是短暂的,并且其生命周期由消费者控制。相反,应该为概念上需要创建运行时数据(由消费者提供)的依赖项创建抽象工厂。
但即使工厂方法包含参数,也必须小心以确保确实需要抽象工厂。代理模式通常(但不总是)更适合,因为它允许消费者有一个单一的依赖,而不是依赖于工厂和它的产品。
依赖注入促进了应用程序启动路径中类的组合,本书将这一概念称为组合根。组合根是靠近该应用程序入口点(您的Main
方法)的位置,它了解系统中的每个其他模块。
因为 Composition Root 依赖于系统中的所有其他模块,所以在 Composition Root 中消耗 Abstract Factories 通常意义不大。例如,如果您定义了一个IXFactory
抽象来产生IX
依赖关系,但 Composition Root 是该IXFactory
抽象的唯一使用者,那么您正在解耦一些不需要解耦的东西:Composition Root 本质上以任何方式了解系统的所有其他部分.
您的IGeneticAlgorithmFactory
抽象似乎就是这种情况。它的唯一消费者似乎是您的组合根。如果这是真的,则可以简单地删除此抽象及其实现,并且可以简单地将其getInstance
方法中的代码移动到MainProgram
类中(该类用作您的组合根)。
我很难理解你的IIndividual
实现是否需要一个工厂(至少 14 年前我在大学实现了遗传算法),但它们看起来更像是运行时数据而不是“真正的”依赖项。所以工厂在这里可能有意义,尽管要验证它们的创建和实现是否必须隐藏在抽象之后。当直接FastGeneticAlgorithm
创建SmallIndividual
实例时,我可以想象应用程序是足够松散耦合的。然而,这只是一个疯狂的猜测。
最重要的是,最佳实践是应用构造函数注入。这可以防止时间耦合。此外,不要像您AbstractGeneticAlgorithm
一样在定义的抽象中指定实现依赖项。这使抽象成为泄漏抽象(这是 DIP 违规)。相反,通过将它们声明为实现上的构造函数参数来声明依赖项(FastGeneticAlgorithm
在您的情况下)。
但即使存在IIndividualFactory
,您的代码也可以通过以下最佳实践来简化:
// Use interfaces rather than base classes. Prefer Composition over Inheritance.
public interface IGeneticAlgorithm { ... }
public interface IIndividual { ... }
public interface IIndividualFactory {
public IIndividual getInstance();
}
// Implementations
public class FastGeneticAlgorithm implements IGeneticAlgorithm {
private IIndividualFactory individualFactory;
// Use constructor injection to declare the implementation's dependencies
public FastGeneticAlgorithm(IIndividualFactory individualFactory) {
this.individualFactory = individualFactory;
}
}
public class SmallIndividual implements IIndividual { }
public class SmallIndividualFactory implements IIndividualFactory {
public IIndividual getInstance() {
return new SmallIndividual();
}
}
public static class Program {
public static void main(String[] args){
AbstractGeneticAlgorithm algoritm = CreateAlgorithm();
algoritm.makeIndividual();
}
private AbstractGeneticAlgorithm CreateAlgorithm() {
// Build complete object graph inside the Composition Root
return new FastGeneticAlgorithm(new SmallIndividualFactory());
}
}
添加回答
举报