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());
}
}
添加回答
舉報