Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现单例模式_Java_Design Patterns_Singleton - Fatal编程技术网

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(); 
  }