Java 实现单例模式
如果我们将一个类实现为一个单例,我们将执行以下操作Java 实现单例模式,java,design-patterns,singleton,Java,Design Patterns,Singleton,如果我们将一个类实现为一个单例,我们将执行以下操作 class Single { private Single singleton; public static Single getInstance() { if(null == singleton) { singleton = new Single(); } return singleton; } //then we make the constructor private
class Single
{
private Single singleton;
public static Single getInstance()
{
if(null == singleton)
{
singleton = new Single();
}
return singleton;
}
//then we make the constructor private
private Single()
{
}
}
考虑到上述情况,重写clone()是否也是一个好主意,以防止类的多个实例?如果不实现clonable,则不应实现clonable。 附笔 一个更干净的java单体是:
class Single {
private static final Single singleton = new Single();
private Single() { }
public static Single getInstance() {
return single;
}
}
Cloneable
界面中没有clone()
方法。同样,如果您的类没有实现Cloneable
,那么
这就是说,克隆是目前在编写良好的Java中很少发生的事情。正如Josh Bloch用有效的Java编写的,第11项:
Cloneable
界面旨在作为对象的混入界面(项目18)
宣传他们允许克隆。不幸的是,它未能达到这一目的。它的
主要缺陷是缺少克隆
方法,并且对象
的克隆方法受到保护。
如果不诉诸反射(第53项),则无法调用克隆
方法仅因为它实现了可克隆性
。甚至是一个反省的人
调用可能会失败,因为无法保证对象具有可访问的
克隆
方法。尽管存在这一缺陷和其他缺陷,但该设施仍在广泛使用,因此值得一试
理解它
…基本上,人们不/不应该使用clone()
。这是一个设计拙劣的接口,如果您希望您的对象是可克隆的,最好提供一个复制构造函数或复制工厂方法(从第11项中窃取的代码):
当我谈论有效的Java时,有一种更好的方法来编写单例,假设您确实需要一个单例(这是一个很大的假设!) 从1.5版开始,有第三种实现单例的方法。简单地 使用一个元素创建枚举类型: 该方法在功能上等同于公共领域方法,只是 更简洁,免费提供序列化机制,并提供 铁一般的保证,即使面对复杂的 序列化或反射攻击。然而,这种方法尚未得到广泛应用 已采用,单元素枚举类型是实现单例的最佳方式。默认情况下,clone()方法标记为受保护,但如果您的类扩展了另一个支持克隆的类,则可能会违反单例的设计原则 在这种情况下,是的,这是一个好主意:
public Object clone()
throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}
对singleton对象的任何clone()
调用都将失败,如下所述:
如果类不可克隆
(未指定实现可克隆
),将抛出克隆不支持异常
错误
所以不,没有必要。代码越少越好:)如前所述,没有什么可以重写的。一般来说,单例实现有很多缺陷(除了代码示例中的明显错误)。考虑多线程、反射、序列化/反序列化。将其作为一个带有1个常量的枚举将更容易,因为您不必编写任何代码来强制执行该属性
看看另一个问题的答案(忽略关于
hashCode()
)的部分)。还要注意注释。不要尝试延迟实例化它,几乎没有任何意义,重写一个不可见的受保护方法毫无意义,尽管它确实有意义。通常,在调用super.clone()之前/之后,人们会重写clone()方法以提供一些特殊功能。clone()相关:相关:线程安全惰性初始化:它不干净。它是渴望,而原始是懒惰。这归结为当你引用类。。。为什么要引用该类而不调用getInstance(),除非它也有您想要访问的静态变量。这样做也是线程安全的。您的选择取决于您需要什么。是的,但这种方式是通用的goto解决方案。是的,wiki将其命名为“传统的简单方式”:-)有一个clone()方法要覆盖。正如您所说,它位于Object.clone()上。
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
public Object clone()
throws CloneNotSupportedException
{
throw new CloneNotSupportedException();
}