亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

告訴低級對象使用哪些工廠的好方法是什么?

告訴低級對象使用哪些工廠的好方法是什么?

瀟瀟雨雨 2021-10-28 15:44:02
我最近學習了很多關于設計模式的知識,特別是依賴注入。我很確定抽象工廠是實例化具有依賴關系的對象的好方法。但是我不確定如何告訴低級對象他們應該使用哪些工廠??紤]以下簡化示例:我有一個類 MainProgram (我只是為了表示我的程序中還有其他代碼......)在運行時的某個時刻,我想用抽象工廠實例化 IGeneticAlgorithm:public class MainProgram{    private AbstractGeneticAlgorithm geneticAlgorithm;    private IGeneticAlgorithmFactory geneticAlgorithmFactory;    public MainProgram(IGeneticAlgorithmFactory geneticAlgorithmFactory){        this.geneticAlgorithmFactory = geneticAlgorithmFactory;    }    private void makeGeneticAlgorithm(){        geneticAlgorithm = geneticAlgorithmFactory.getInstance();    }    public static void main(String[] args){        MainProgram mainProgramm = new MainProgram(new FastGeneticAlgorithmFactory());        //...    }}public interface IGeneticAlgorithmFactory{    public IGeneticAlgorithm getInstance();}public class FastGeneticAlgorithmFactory implements IGeneticAlgorithmFactory{    public IGeneticAlgorithm getInstance(){        return new FastGeneticAlgorithm();    }}public abstract class AbstractGeneticAlgorithm{    private IIndividual individual;    private IIndividualFactory individualFactory;    private void makeIndividual(){        individual = individualFactory.getInstance();    }    //...}在運行時的某個時刻,我想在我的 GeneticAlgorithm 中實例化一個 IIndividual。IIndividual 不能在啟動時實例化。能夠在運行時實例化 IIndividual 的需要來自遺傳算法的工作方式,基本上在選擇-重組-變異的每個步驟之后,必須實例化新的個體。(有關更多信息,請參閱https://en.wikipedia.org/wiki/Genetic_algorithm)。我選擇在這里只給 AbstractGeneticAlgorithm 一個 IIndividual 以保持這個例子簡單。public class FastGeneticAlgorithm implements AbstractGeneticAlgorithm{    private IIndividual individual;     private IIndividualFactory individualFactory;}使 SmallIndividualFactory 成為 FastGeneticAlgorithm 中的靜態變量在我看來并不是好的做法。并將 SmallIndividualFactory 傳遞給 Main,以便 Main 可以將其傳遞給 FastGeneticAlgorithm 似乎也不正確。我的問題是如何解決這個問題?謝謝你。
查看完整描述

1 回答

?
哈士奇WWW

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());

    }

}


查看完整回答
反對 回復 2021-10-28
  • 1 回答
  • 0 關注
  • 163 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號