我最好用一个例子来解释这个问题。 我有一个接口模型,可用于访问数据。 可以有不同的Model实现,它们可以表示各种格式的数据,例如XMl,txt格式等。模型与格式无关。 可以说一个这样的实现是 myxmlModel 。
现在我想强制 myxmlModel 以及模型的每个其他实现都遵循 Singleton Pattern 。通常的方法是使 myxmlModels 构造函数private并提供一个静态工厂方法来返回myModel类的实例。但问题是接口不能有静态方法定义,结果我不能强制执行特定的Factory方法定义所有模型的实现。因此,一个实现可能会以提供 getObject()结束,而其他实现可能会获得 NewModel()。。
一个解决方法是允许对 myxmlModel的构造函数进行包访问,并创建一个Factory类,该类创建 myxmlModel 对象并将其缓存以供进一步使用。
我想知道是否有更好的方法来实现相同的功能。
答案 0 :(得分:4)
public enum MyXMLModel{
INSTANCE();
//rest of class
};
编辑: 另一种可能性是创建执行所有工作的委托类,然后使用枚举来提供所有模型选项。
例如:
class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}
class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}
public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());
private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }
public void foo() { delegate.foo(); }
}
答案 1 :(得分:2)
您可以使用反射。像这样:
public interface Model {
class Singleton {
public static Model instance(Class<? extends Model> modelClass) {
try {
return (Model)modelClass.getField("instance").get(null);
} catch (blah-blah) {
blah-blah
}
}
}
public class XmlModel implements Model {
private static final Model instance = new XmlModel();
private XmlModel() {
}
}
用法:
Model.Singleton.instance(XmlModel.class)
实际上,我不太喜欢这段代码:)。首先,它使用反射 - 非常慢,第二 - 如果类的定义错误,则存在运行时错误的可能性。
答案 2 :(得分:0)
您可以将接口重构为抽象类吗?这将允许您将特定的工厂方法强制降低到所有实现类。
答案 3 :(得分:0)
我曾经问过自己同样的问题。我提出了相同的答案; - )
现在我通常会放弃“强制”行为,我依靠文档。 我没有发现Singleton方面如此引人注目以至于需要通过各种方式强制执行的情况。 这只是该项目的“最佳实践”。
我通常使用Spring来实现这样的对象, 并且Spring配置使它成为Singleton。 安全,如此简单......加上额外的Spring优势(例如Proxying,替换一个不同的对象进行一些测试等等)
答案 4 :(得分:0)
这更能回答您对kts答案的评论/澄清。是这样,真正的问题是不使用Singleton模式,而是定义一个允许贡献单身的eclipse(equinox)扩展点模式?
我认为,这是无法做到的,因为每次调用IConfigurationElement.createExecutableExtension时都会创建一个新实例。这与您的单身人士要求完全不相容。因此,您需要公共默认构造函数,以便每个人都可以创建实例。
除非您可以更改扩展点定义,以便插件提供ModelFactory而不是模型,例如
public interface ModelFactory {
public Model getModelInstance();
}
因此扩展用户将实例化ModelFactory并使用它来获取单例。
如果我猜错了,请留言并删除答案;)