Реализация шаблона Singleton - PullRequest
2 голосов
/ 08 февраля 2011

Если мы реализуем класс как синглтон, мы делаем следующее

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 (), а также предотвратить несколько экземпляров класса?

Ответы [ 5 ]

5 голосов
/ 08 февраля 2011

В интерфейсе Cloneable нет метода clone().Как @ Иван указывает на , если ваш класс не реализует Cloneable, тогда вызов Single#clone() выдаст CloneNotSupportedException.


Это сказалоКлонирование - это то, что редко происходит в хорошо написанной Java в наши дни.Как пишет Джош Блох в Effective Java , Item 11:

Интерфейс Cloneable был задуман как mixin interface (Item 18) для объектоврекламировать, что они разрешают клонирование.К сожалению, он не служит этой цели.Его основной недостаток - отсутствие метода clone, а метод клонирования Object защищен.Вы не можете, не прибегая к рефлексии (пункт 53), вызывать метод clone для объекта только потому, что он реализует Cloneable.Даже рефлексивный вызов может потерпеть неудачу, поскольку нет гарантии, что объект имеет доступный метод clone.Несмотря на этот и другие недостатки, средство широко используется, поэтому стоит его понять.

... в основном люди не / не должны использовать clone().Это плохо спроектированный интерфейс, и если вы хотите, чтобы ваши объекты были клонируемыми, лучше предоставить конструктор копирования или метод фабрики копирования (код, украденный из элемента 11):

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

И пока яЯ имею в виду Эффективная Java , есть лучший способ написать синглтон, при условии, что вам действительно нужен один (что очень важно!).

Начиная с версии 1.5, существует третий подход к реализации синглетонов.Просто создайте тип enum с одним элементом:

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

Этот подход функционально эквивалентен подходу открытого поля, за исключением того, что он более лаконичен, предоставляет механизм сериализации бесплатно и обеспечивает железную оболочкугарантия от множественных реализаций, даже перед лицом сложных сериализаций или атак отражения.Хотя этот подход еще не получил широкого распространения, одноэлементный тип перечисления является лучшим способом реализации синглтона.

2 голосов
/ 08 февраля 2011

Любые вызовы clone() для вашего одноэлементного объекта завершатся неудачно, как описано здесь:

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

Если класс не Cloneable (не указывает implements Cloneable), будет выдана ошибка CloneNotSupportedException.

Так нет, это не обязательно. И меньше кода goooood:)

2 голосов
/ 08 февраля 2011

если вы не реализуете клонирование, оно не должно быть клонируемым.ps чище сингл java это:

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

 public static Single getInstance() {
  return single;
 }
}
0 голосов
/ 08 февраля 2011

Как сказал он , нечего переопределять.
Что касается вашей одноэлементной реализации в целом - в ней много, много недостатков (кроме очевидных ошибок в примере кода). Подумайте о многопоточности, рефлексии, сериализации / десериализации. Сделать это как перечисление с 1 константой будет намного проще с вашей стороны, так как вам не нужно будет писать код для реализации свойства.

Взгляните на этот ответ на другой вопрос (не обращайте внимания на часть о hashCode()). Также обратите внимание на комментарии.

0 голосов
/ 08 февраля 2011

По умолчанию метод clone () помечен как защищенный, но если ваш класс расширяет другой класс, поддерживающий клонирование, возможно нарушение принципов разработки синглтона.

В таком случае, да, это хорошая идея:

 public Object clone()
    throws CloneNotSupportedException
  {
    throw new CloneNotSupportedException(); 
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...