实现单例模式

发布于 2024-10-16 05:15:19 字数 352 浏览 1 评论 0原文

如果我们将一个类实现为单例,我们会执行以下操作

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()以防止该类的多个实例是一个好主意吗?

If we are implementing a class as a singleton, we do the following

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

Considering the above, wiil it be a good idea to override clone() as well to prevent multiple instances of the class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雄赳赳气昂昂 2024-10-23 05:15:19

Cloneable 接口中没有 clone() 方法。正如 @Ivan 指出的,如果你的类没有实现 Cloneable 然后 调用Single#clone() 将抛出 CloneNotSupportedException


也就是说,克隆现在在编写良好的 Java 中很少发生。正如 Josh Bloch 在《Effective Java》第 11 条中所写:

Cloneable 接口旨在作为一个mixin 接口(第 18 项),供对象
宣传他们允许克隆。不幸的是,它未能达到这个目的。它是
主要缺陷是它缺少clone方法,而Object的clone方法受到保护。
如果不借助反射(第 53 项),您就无法调用克隆
对象上的方法仅仅因为它实现了Cloneable。即使是反光的
调用可能会失败,因为不能保证该对象具有可访问的
克隆方法。尽管存在这个缺陷和其他缺陷,该设施仍在广泛使用,因此值得
明白了。

...基本上,人们不会/不应该使用clone()。这是一个设计得很糟糕的接口,如果你希望你的对象是可克隆的,最好提供一个复制构造函数或复制工厂方法(从条款 11 中窃取的代码):

public Yum(Yum yum); // copy constructor
public static Yum newInstance(Yum yum); // copy factory

当我谈论 Effective Java,有一种更好的方法来编写单例,假设您确实需要一个(这是一个很大的假设!)。

从 1.5 版开始,有第三种方法来实现单例。简单地
使用一个元素创建一个枚举类型:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

这种方法在功能上等同于公共字段方法,不同之处在于它
更加简洁,免费提供序列化机制,并提供
即使面对复杂的情况,也能坚决保证防止多重实例化
序列化或反射攻击。虽然这种方法尚未广泛推广
采用,单元素枚举类型是实现单例的最佳方式。

There is no clone() method in the Cloneable interface. As @Ivan points out, if your class does not implement Cloneable then calling Single#clone() will throw a CloneNotSupportedException.


That said, cloning is something that happens infrequently in well-written Java these days. As Josh Bloch writes in Effective Java, Item 11:

The Cloneable interface was intended as a mixin interface (Item 18) for objects to
advertise that they permit cloning. Unfortunately, it fails to serve this purpose. Its
primary flaw is that it lacks a clone method, and Object's clone method is protected.
You cannot, without resorting to reflection (Item 53), invoke the clone
method on an object merely because it implements Cloneable. Even a reflective
invocation may fail, as there is no guarantee that the object has an accessible
clone method. Despite this flaw and others, the facility is in wide use so it pays to
understand it.

...basically, people don't/shouldn't use clone(). It's a poorly designed interface, and if you want your objects to be cloneable, it's better to provide a copy constructor or copy factory method (code stolen from Item 11):

public Yum(Yum yum); // copy constructor
public static Yum newInstance(Yum yum); // copy factory

And while I'm talking about Effective Java, there's a better way to write a singleton, assuming that you really do need one (which is a big if!).

As of release 1.5, there is a third approach to implementing singletons. Simply
make an enum type with one element:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

This approach is functionally equivalent to the public field approach, except that it
is more concise, provides the serialization machinery for free, and provides an
ironclad guarantee against multiple instantiation, even in the face of sophisticated
serialization or reflection attacks. While this approach has yet to be widely
adopted, a single-element enum type is the best way to implement a singleton.

压抑⊿情绪 2024-10-23 05:15:19

如果你不实现 clonable 它就不应该是可克隆的。
附注
更干净的java单是:

class Single { 
 private static final Single singleton = new Single();
 private Single() { }

 public static Single getInstance() {
  return single;
 }
}

if you dont implement clonable it should not be clonable.
p.s.
a cleaner java single is:

class Single { 
 private static final Single singleton = new Single();
 private Single() { }

 public static Single getInstance() {
  return single;
 }
}
小傻瓜 2024-10-23 05:15:19

对单例对象的任何 clone() 调用都将失败,如下所述:

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#clone%28 %29

如果该类不是Cloneable(未指定实现 Cloneable),则会引发 CloneNotSupportedException 错误。

所以不,没有必要。代码越少越好:)

Any calls to clone() on your singleton object will fail, as explained here:

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#clone%28%29

If the class is not Cloneable (does not specify implements Cloneable), a CloneNotSupportedException error will be thrown.

So no, it's not necessary. And less code is goooood :)

半岛未凉 2024-10-23 05:15:19

默认情况下,clone() 方法被标记为受保护,但如果您的类扩展了另一个支持克隆的类,则可能会违反单例的设计原则。

在这种情况下,是的,这是一个好主意:

 public Object clone()
    throws CloneNotSupportedException
  {
    throw new CloneNotSupportedException(); 
  }

By default, the clone() method is marked as protected, but if your class extends another class that does support cloning, it is possible to violate the design principles of the singleton.

In that case, yes this is a good idea:

 public Object clone()
    throws CloneNotSupportedException
  {
    throw new CloneNotSupportedException(); 
  }
小伙你站住 2024-10-23 05:15:19

正如所说,没有什么可以覆盖的。
一般来说,关于您的单例实现 - 它有很多很多缺陷(除了代码示例中的明显错误)。考虑多线程、反射、序列化/反序列化。将其作为具有 1 个常量的枚举对您来说会更容易,因为您不必编写任何代码来强制执行该属性。

看看这个对另一个问题的回答(忽略有关 hashCode() 的部分)。还要注意评论。

As he said, there is nothing to override.
Regarding your singleton implementation in general - there are many, many flaws with it (apart from the obvious mistakes in the code sample). Think about multithreading, reflection, serialization/deserialization. Making it as an enum with 1 constant will be much easier on your side since you won't have to write any code to enforce the property.

Take a look at this answer to another question (disregard the part about hashCode()). Also take note of the comments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文