有人可以幫助新手程序員瞭解他的解決方案是否正確?正確的方法來防止子類實例化,而無需調用所需的初始化方法?
我的問題是類似以下兩種:
What's wrong with overridable method calls in constructors?
Factory pattern in C#: How to ensure an object instance can only be created by a factory class?
問題:我想有子類,這將區別僅在他們的初始化方法。但是,我也想阻止在沒有初始化的情況下實例化這些類。換句話說,我要確保,有些「初始化()」方法將總是被子類的實例化後稱爲:
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
loadData(); // should be called to initialise class fields and ensure correct work of other class methods
}
protected abstract loadData(){
... //uses dataSource
}
}
所以我決定在一個構造函數進行初始化。它的工作(現在我知道,這是一個非常糟糕的實踐),直到我創建了一個子類,其中initialize方法中使用一些額外的參數:
public class DataFromSpecificSources extends Data {
private Parameter dataSource2;
public DataFromSpecificSources(parameter1, parameter2){
this.dataSource2 = parameter2; // I can't put it here because the constructor is not called yet
super(parameter1); // this, of course, will not work
}
@Override
private void loadData(){
... // uses both dataSource 1 and 2
// or just dataSource2
}
}
這當然是行不通的。我開始尋找右側圖案......當我閱讀問題的答案之前發佈,我決定用子類構造函數的工廠並限制能見度包:
我的解決辦法:
// factory ensures that loadData() method will be called
public class MyDataFactory(){
public Data createSubClass(parameter1,parameter2){
Data subClass;
if (parameter2 != null){
subClass = new DataFromSpecificSources(parameter1, parameter2);
subClass.loadData();
} else {
subClass = new AnotherSubClass(parameter1);
subClass.loadData()
}
return subClass;
}
}
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
}
// I don't call it in constructor anymore - instead it's controlled within the factory
protected abstract loadData(){
... //uses dataSource
}
}
public class DataFromSpecificSources {
private Parameter dataSource2;
protected DataFromSpecificSources(){}
// now this constructor is only visible within package (only for the factory in the same package)
DataFromSpecificSources(parameter1, parameter2){
super(parameter1); // it does not initialise data anymore
this.dataSource2 = parameter2;
}
@Override
protected void loadData(){
... // uses dataSources 1 and 2
}
}
現在工廠確保子類將被初始化(數據將被加載)並且在其他包中不允許實例化子類。其他類無法訪問子類的構造函數,並且被迫使用工廠來獲取子類的實例。
我只是想問,如果我的解決方案是正確的(邏輯上)和工廠方法的子類構造函數可見性限於包是正確的選擇在這裏?或者還有其他更有效的模式解決問題?!
優質解決方案。然而,工廠是否需要成爲自己的班級?工廠方法可以在'Data'中作爲靜態方法嗎? –
@JohnB由於他選擇的實現取決於參數,我會說不,工廠類是一個更好的選擇。 – Brian