初心者のプログラマーが自分のソリューションが正しいかどうかを理解するのを誰かが助けることができますか?
私の質問は、次の 2 つに似ています。
コンストラクターでのオーバーライド可能なメソッド呼び出しの何が問題になっていますか?
C#のファクトリパターン:オブジェクトインスタンスがファクトリクラスによってのみ作成されるようにする方法は?
問題:初期化方法のみが異なるサブクラスが必要です。ただし、これらのクラスを初期化せずにインスタンス化することも避けたいと考えています。言い換えれば、サブクラスのインスタンス化後に必ず「initialize()」メソッドが呼び出されるようにしたいのです。
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
}
}
そこで、コンストラクターで初期化を実行することにしました。初期化メソッドがいくつかの追加パラメーターを使用するサブクラスを作成するまで、それは機能しました(これは非常に悪い習慣であることがわかりました):
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
}
}
ファクトリにより、サブクラスが初期化され (データがロードされます)、サブクラスのインスタンス化が他のパッケージで許可されないことが保証されます。他のクラスはサブクラスのコンストラクタにアクセスできず、ファクトリを使用してサブクラスのインスタンスを取得する必要があります。
私のソリューションが(論理的に)正しいかどうかを尋ねたかっただけで、サブクラスコンストラクターの可視性がパッケージに制限されたFactoryメソッドがここで正しい選択ですか?! または、問題を解決する他のより効果的なパターンはありますか?!