[英]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.