我正在开发一个设计模式,我想确保这里只是Java虚拟机中一个类的一个实例,通过一个点汇集一些资源的所有请求,但我不知道它是否是可能的。
我只能想到一种计算类实例的方法,并在创建第一个实例后销毁所有实例。
这是一种正确的方法吗?如果没有,还有其他方法吗?
答案 0 :(得分:28)
使用单件模式。最简单的实现包括private constructor
和field
来保存其结果,以及static
访问器方法,其名称为getInstance()
。
私有字段可以在静态初始化程序块中分配,或者更简单地使用初始化程序分配。 getInstance()
方法(必须是公共的)然后只返回此实例
public class Singleton {
private static Singleton instance;
/**
* A private Constructor prevents any other class from
* instantiating.
*/
private Singleton() {
// nothing to do this time
}
/**
* The Static initializer constructs the instance at class
* loading time; this is to simulate a more involved
* construction process (it it were really simple, you'd just
* use an initializer)
*/
static {
instance = new Singleton();
}
/** Static 'instance' method */
public static Singleton getInstance() {
return instance;
}
// other methods protected by singleton-ness would be here...
/** A simple demo method */
public String demoMethod() {
return "demo";
}
}
请注意在getInstance()
方法中使用“延迟评估”的方法
在Design Patterns中提倡,在Java中不是必需的,因为Java已经使用了“懒惰”
加载。“你的单例类可能不会被加载,除非它getInstance()
被称为,所以没有必要试图推迟单身人士的建设,直到需要它为止
通过getInstance()
测试null
的单例变量并创建单例
那里。
使用此类同样简单:只需获取并保留引用,并在其上调用方法:
public class SingletonDemo {
public static void main(String[] args) {
Singleton tmp = Singleton.getInstance();
tmp.demoMethod();
}
}
一些评论员认为单身人士也应提供公开决赛
只抛出异常的clone()
方法,以避免“作弊”的子类
clone()
单身人士。但是,显然只有一个私有构造函数的类
不能被分类,所以这种偏执似乎没有必要。
答案 1 :(得分:5)
您需要Singleton
模式。有excellent discussion如何正确实现这一点。如果你这样做,那么只有一个类的实例。
基本上你要做的是创建一个类,在静态级别保存该类的单个实例化对象,并提供一个静态访问器来获取它(getInstance()
或类似的)。使构造函数最终,这样人们就无法创建自己的实例。上面的链接对如何做到这一点有很多很好的建议。
答案 2 :(得分:5)
这是众所周知的Singleton模式:您可以按如下方式实现:
public class SingletonClass {
//this field contains the single instance every initialized.
private static final instance = new SingletonClass();
//constructor *must* be private, otherwise other classes can make an instance as well
private SingletonClass () {
//initialize
}
//this is the method to obtain the single instance
public static SingletonClass getInstance () {
return instance;
}
}
然后使用:
调用实例(就像构建非单例一样)SingletonClass.getInstance();
但在文献中, Singleton 通常被认为是bad design idea。当然,这在某种程度上取决于具体情况,但大多数程序员都反对。只说出来,不要向信使开枪......
答案 3 :(得分:5)
有一种思想流派认为单身人士模式实际上是一种反模式。
考虑到你只希望拥有A类的A类,那么另一种选择是拥有一个构建器或工厂类,它本身限制了A类对象数量的创建,并且可以通过一个简单的计数器。 优点是A级不再需要担心,它专注于其真正的目的。每个使用它的类不再需要担心它是单例(不再需要getInstance()调用)。
答案 4 :(得分:4)
使用枚举。在Java中,enum是创建单例的唯一真正方法。私有构造函数仍然可以通过反射来调用。
有关详细信息,请参阅此StackOverflow问题: Implementing Singleton with an Enum (in Java)
讨论: http://javarevisited.blogspot.com/2012/07/why-enum-singleton-are-better-in-java.html
答案 5 :(得分:3)
我只能想到一种计算类实例的方法,并在创建第一个实例后销毁所有实例。这是一种正确的方法吗?如果没有,还有其他方法吗?
正确的技术方法是将类的所有构造函数声明为private
,以便类的实例只能由类本身创建。然后你只编写类来创建一个实例。
其他答案显示了实现这一目标的一些方法,根据" Singleton"设计模式。但是,实现像这样的单例有一些缺点,包括使编写单元测试变得更加困难。
答案 6 :(得分:2)
我更喜欢懒惰的单例类,它会覆盖readResolve方法。
对于Serializable和Externalizable类,readResolve方法允许类在返回到调用者之前替换/解析从流中读取的对象。通过实现readResolve方法,类可以直接控制自己反序列化的实例的类型和实例。
使用/Initialization-on-demand_holder_idiom的懒惰单身人士:
public final class LazySingleton {
private LazySingleton() {}
public static LazySingleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazySingleton INSTANCE = new LazySingleton();
}
private Object readResolve() {
return LazyHolder.INSTANCE;
}
}
主要提示:
final
关键字禁止通过子类化扩展此类private
构造函数禁止在调用者类中使用new
运算符创建直接对象readResolve
禁止在对象反序列化期间创建多个类实例答案 7 :(得分:1)
为此您需要使用单例模式,我只是发布了一个可能对您有用的演示代码。
例如:如果我只想要一个这个Connect
类的对象:
public final class Connect {
private Connect() {}
private volatile static Connect connect = null;
public static Connect getinstance() {
if(connect == null) {
synchronized (Connect.class) {
connect = new Connect();
}
}
return connect;
}
}
此处构造函数是私有的,因此没有人可以使用new
关键字来创建新实例。
答案 8 :(得分:0)
class A{
private A(){
}
public static A creator(A obj){
A ob=new A();
return ob;
}
void test(){
System.out.println("The method is called");
}
}
class Demo{
public static void main(String[] args){
A ob=null;
ob=A.creator(ob);
ob.test();
}
}