【发布时间】:2012-09-07 18:32:56
【问题描述】:
有人可以帮助新手程序员了解他的解决方案是否正确吗?
我的问题类似于以下两个:
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?
问题:我想要子类,它们的不同之处仅在于它们的初始化方法。但是,我还想防止在没有初始化的情况下实例化这些类。换句话说,我想确保在子类实例化后会始终调用某些“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
}
}
所以我决定对构造函数进行初始化。它有效(现在我知道这是一个非常不好的做法),直到我创建了一个子类,其中 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 由于他对实现的选择取决于参数,我会说不,工厂类是更好的选择。
标签: java design-patterns inheritance overriding factory