我有两个扩展抽象模型的类。这两个类都实现了一个名为instance()的方法,基本上确保了任何时候只有一个类的实例。 instance()的结构对于这两个类完全相同,所以我认为将它提升到抽象类是很好的。但是,该方法调用实例化类'默认构造函数。是否可以从抽象类中调用此构造函数?如果是这样的话?还有哪些其他方法可用于推广这种方法?
我有一个类似于
的模型的抽象类public abstract class Models{
public List<Model> models = new ArrayList<Model>();
/** load the different models, with the models with pre-trained model*/
public abstract void load();
}
还有两个类似于此的实时课程
public class PageLanguageModels extends Models {
/** ensure we only call one of them */
protected static PageLanguageModels _instance = null;
static Logger logger = Logger.getLogger(ProductLanguageModels.class.getName());
public static synchronized PageLanguageModels instance() {
if (_instance == null) {
try {
_instance = new PageLanguageModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
/** load the different models, with the models with pre-trained model*/
@Override
public void load() {
models.clear();
models.add(new BOWModel());
}
}
public class ProductLanguageModels extends Models {
/** ensure we only call one of them */
protected static ProductLanguageModels _instance = null;
static Logger logger = Logger.getLogger(ProductLanguageModels.class.getName());
public static synchronized ProductLanguageModels instance() {
if (_instance == null) {
try {
_instance = new ProductLanguageModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
/** load the different models, with the models with pre-trained model*/
@Override
public void load() {
models.clear();
models.add(new Word2VecModel());
}
}
我尝试使用工厂方法模式,但这不起作用,因为实例是静态方法,并且无法从静态方法调用抽象工厂方法。
无法对非静态方法makeModels()进行静态引用 来自型号
public abstract class Models{
/** load the different models, with the models with pre-trained model*/
public abstract void load();
//Factory method
public abstract Models makeModels();
// Instance code moved up from instanciating classes
protected static Models _instance = null;
static Logger logger = Logger.getLogger(Models.class.getName());
public static synchronized Models instance() {
if (_instance == null) {
try {
_instance = makeModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
}
答案 0 :(得分:2)
我不认为您可以将所有实例化逻辑移动到父类,因为它具有静态特性和类型擦除问题,但您肯定可以组织代码以使其可重用。我通过专注于实例化部分更改您的设计,为您编写了一个简单的复制/粘贴示例,因此我遗漏了一些属性并记录了代码:
界面
public interface Models {
void load();
}
抽象实现
public abstract class BaseModels implements Models {
protected static <T extends Models> T instance(Class<T> type, T candidate) {
if (candidate == null) {
try {
candidate = type.newInstance();
candidate.load();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
return candidate;
}
}
具体实施
public class HeroModels extends BaseModels {
static HeroModels instance;
public static HeroModels instance() {
instance = instance(HeroModels.class, instance);
return instance;
}
@Override
public void load() {
System.out.println("Loading HeroModels...");
}
}
一个简单的测试用例
public class TestDrive {
@Test
public void testEquality() {
HeroModels a1 = HeroModels.instance();
HeroModels a2 = HeroModels.instance();
Assert.assertEquals(a1, a2);
System.out.println("a1: " + a1);
System.out.println("a2: " + a2);
}
}
测试用例输出
Loading HeroModels...
a1: HeroModels@736e9adb
a2: HeroModels@736e9adb
从输出中可以看到HeroModels
类只加载了一次。 instance(...)
类中的BaseModel
方法受到保护,以明确它旨在供子级使用,子级可能具有自己的静态实例属性。
答案 1 :(得分:-1)
是的,但您可能希望将其提取到单独的类中。