簡體   English   中英

將屬性傳遞給Factory方法

[英]Passing Properties to Factory method

我有一個工廠方法,它返回一個接口的實現。 問題是 - 實現具有不同的構造函數參數。

我的問題是 - 如何通過工廠方法將參數傳遞給接口的不同實現?

我有一個想法,但我不確定它是否有意義 - 將Properties對象傳遞給工廠方法? 這樣,每個接口實現都可以獲得其構造函數所需的屬性,而工廠接口將統一。

這有意義,還是有更好的解決方案?

我決定添加一個例子,所以我可以更好地澄清問題。

假設我們有接口SomeAlgorithm ,我們有具體的算法,每個算法可能有不同的參數,例如

SomeAlgorithm algo = new Algo1();
SomeAlgorithm algo = new Algo2(noOfIterations);
SomeAlgorithm algo = new Algo3(precision, boundary);

我希望能夠做類似的事情

SomeAlgorithm algo = AlgoFactory.getAlgo("algoName");

我處理不同參數的方法是

SomeAlgorithm algo = AlgoFactory.getAlgo("algoName", properties); 

然后,如果算法具有參數(例如Algo1沒有參數),AlgoFactory可以將適當的屬性傳遞給具體的算法構造函數。 如果某些屬性不存在,則可以傳遞默認值(如果算法中需要該值)。

如您所見,我希望能夠動態更改算法。 用戶將在運行時選擇算法並傳遞適當的參數,這些參數將被放入屬性對象中。

這有意義嗎?

已編輯問題的更新 (rev43552065-8ee8-47e8-bc96-c660c3836998):

您的示例不是典型的工廠模式。 如果您需要通過名稱引用三種算法並為特定算法提供特定參數,那么您為什么要使用工廠? 你應該從着名的“Effective Java”一書中讀到“第1項:考慮靜態工廠方法而不是構造函數”。 它描述了工廠方法的優點,我在你的例子中沒有看到。


這個問題有很多解決方案,你可以在各種流行的項目中找到數百個例子。

例如, DriverManager類使用類似URL的字符串,其中包含變量格式的連接詳細信息和帶有高級選項的其他Properties對象( 示例 )。

工廠方法通常應該足夠抽象以獲得有效的實現,而無需為特定實現指定任何其他參數。 它應該“隱藏”實現細節。

如果事實證明有必要傳遞其他/可選屬性,則傳遞一個Properties對象是很常見的。

有不同的策略。 例如, UrlConnection是一個抽象類。 可以通過調用URL.openConnection()來檢索實例,但是,只能通過將返回的UrlConnection轉換為特定的子類型(例如HttpUrlConnection來設置許多選項。

我相信沒有適合所有情況的單一解決方案,我很確定許多解決方案,甚至可能在Java標准庫中,都遠非完美,但你應該真正實現一些簡單而不是浪費太多時間問題。

一種可能的方法,比傳遞Properties以確定結果類型更安全類型,是使用Abstract Factory模式,例如:

// we will be creating subtypes of Vehicle
interface Vehicle {
    void move();
}
class Car implements Vehicle {
    Car(String vehicleId, int seatsNumber) {}
}
class Motorcycle implements Vehicle {
    Motorcycle(String vehicleId) {}
}
// ... via subtypes of VehicleFactory
interface VehicleFactory<T extends Vehicle> {
    T create(String vehicleId);
}
class FourSeatedCarFactory implements VehicleFactory<Car> {
    @Override
    public Car create(String vehicleId) {
        return new Car(vehicleId, 4);
    }
}
class MotorcycleFactory implements VehicleFactory<Motorcycle> {
    @Override
    public Motorcycle create(String vehicleId) {
        return new Motorcycle(vehicleId);
    }
}
class FactoryClient {
    void useVehicle(VehicleFactory<?> factory) {
        factory.create("COOL_PLATE_NAME").move();
    }
}

我看到戰略模式在這里更合適。 您不需要將參數傳遞給構造函數。 他們看起來像params進行計算。

如果您的算法使用相同的工作,例如計算稅,那么就可以這樣做。 但如果他們做不同的事情 - 考慮使用其他方法或提供更多細節,看看可以做些什么。

因此,對於稅收計算,它可以是:

taxCalculator = taxCalculatorFactory.Get(currentCountry);
taxAmount = taxCalculator.Calculate(countrySpecificTaxProperties);

只需為countrySpecificTaxProperties使用一些接口,例如ITaxParams

我認為你需要實現Builder模式。

構建器模式是對象創建軟件設計模式。 與抽象工廠模式和工程方法模式不同,其意圖是啟用多態,建模模式的目的是找到伸縮構造函數反模式的解決方案[需要引證]。

當對象構造函數參數組合的增加導致構造函數的指數列表時,發生伸縮構造函數反模式。

構建器模式不是使用大量構造函數,而是使用另一個對象(構建器),它逐步接收每個初始化參數,然后立即返回生成的構造對象。

看看這個示例代碼。

class SomeAlgorithm{
    // Make it or class or interface
}
class Algo extends SomeAlgorithm{
    private int noOfIterations;
    private double precision; 
    private double boundary;

    public Algo(Builder builder){
        this.noOfIterations = builder.noOfIterations;
        this.precision= builder.precision;
        this.boundary= builder.boundary;
    }
    public String toString(){
        return new StringBuilder("Algo:Iterations:precision:boundary:").append(noOfIterations).append(":").
        append(precision).append(":").append(boundary).toString();
    }
    static class Builder {
        private int noOfIterations; // Mandatory parameter
        private double precision = 1.0; // Optional parameter
        private double boundary = 2.0; // Optional parameter

        public Builder ( int noOfIterations){
            this.noOfIterations = noOfIterations;
        }
        public Builder precision(double precision){
            this.precision = precision;
            return this;
        }
        public Builder boundary(double boundary){
            this.boundary = boundary;
            return this;
        }
        public Algo build(){
            return new Algo(this);
        }
    }
}
public class BuilderDemo{
    public static void main(String args[]){
        Algo algo = new Algo.Builder(2).precision(3.0).boundary(4.0).build();
        System.out.println(algo);
        algo = new Algo.Builder(10).build();
        System.out.println(algo);
    }
}

輸出:

java BuilderDemo 2
Algo:Iterations:precision:boundary:2:3.0:4.0
Algo:Iterations:precision:boundary:10:1.0:2.0

如果必須使用相同的參數集為構造函數和不使用if-else語句實現Factory方法,請查看此替代方法

但我希望獲得相同的結果是:

public static Algo newInstance(String algoClassType) {
    return Class.forName(algoClassType).newInstance();      
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM