Подтвердить что ты не робот

Моделирование Singleton и предотвращение клонирования

Многие статьи, которые я прочитал в Сети о шаблоне проектирования Singleton, отмечают, что класс должен переопределить метод clone() и в нем исключить исключение "CloneNotSupported". Это действительно необходимо?

Метод clone() по умолчанию защищен, поэтому ни один класс (кроме тех, что в одном пакете) не сможет вызвать его на этом экземпляре Singleton. Кроме того, если этот Singleton не реализует Cloneable, то даже если этот метод вызывается, он даст исключение во время выполнения. Кроме того, конструктор является закрытым, мы не сможем подклассифицировать его и тем самым обеспечить его клонирование. Так должен ли я продолжать этот совет для своих классов Singleton?

EDIT: Просто уточнить: я не ищу наилучший способ реализации Singleton. Я просто спрашиваю о правильности упомянутого выше совета, w.r.t "нормального" шаблона Singleton (а не Singleton на основе Enum).

4b9b3361

Ответ 1

Если вы действительно собираетесь использовать синглтон, использовать перечисление из одного элемента и перестать думать об этом.


EDIT: Просто уточнить: я не ищу наилучший способ реализации Singleton. Я просто спрашиваю о правильности упомянутого выше совета, w.r.t "нормального" шаблона Singleton (а не Singleton на основе Enum).

Поскольку у вас есть эффективная Java, тогда вы уже должны знать о подводных камнях и проблемах с Cloneable. Тем не менее, если вы собираетесь реализовать одноэлементный один из "неправильных" способов, нет, нет абсолютно никакой возможности реализовать Cloneable и переопределить Object#clone() просто для того, чтобы бросить CloneNotSupportedException. Object#clone() уже делает это, когда интерфейс Cloneable отсутствует.

Ответ 2

@shrini1000, у вас есть правильный вопрос, но предложение о клоне очень специфичный для следующего условия

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

Вышеописанное необходимо только в том случае, если суперкласс класса singleton реализует метод public clone().

Ответ 3

Следующий код предназначен для предотвращения клонирования класса singleton. Переверните метод clone и выбросите новый CloneNotSupportedException()

public final class SingeltonCloneTest implements Cloneable {

    /**
     * @param args
     * @return
     */
    private static SingeltonCloneTest instance = null;

    private SingeltonCloneTest() {
     System.out.println("Rahul Tripathi");
    }

    public static SingeltonCloneTest getInstance() {

        if (instance == null) {
            instance = new SingeltonCloneTest();
            return instance;
        }
        return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        // TODO Auto-generated method stub
        /*
         * Here forcibly throws the exception for preventing to be cloned
         */
        throw new CloneNotSupportedException();
        // return super.clone();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SingeltonCloneTest test1 = SingeltonCloneTest.getInstance();

        try {
            SingeltonCloneTest test2 = (SingeltonCloneTest) test1.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Ответ 4

См. fooobar.com/questions/4063/... для наиболее безопасного способа применения шаблона Singleton. По существу, сделайте свой Singleton a enum, а не class, с единственным значением INSTANCE.

Ответ 5

При написании класса с использованием шаблона Singleton используется только один экземпляр этот класс может существовать одновременно. В результате класс не должен быть разрешено делать клон.

Синтаксический шаблон говорит, что внутри программы существует только один экземпляр класса, поэтому правильно поднять CloneNotSupportedException в методе Clone().

Ответ 6

Это необходимо, если ваш Singleton-класс расширяет класс, у которого есть видимый метод clone(), определенный в его иерархии.

Ответ 7

Вы можете избежать клонирования, предоставив уже созданному объекту методом clone.

public Object clone() {

return singletoneObject;

}

Ответ 8

Лучший пример, который я нашел, это:

class SingletonSuper implements Cloneable {
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
   }
}

class Singleton2 extends SingletonSuper {
    // 1. Make all constructors private
    private Singleton2() {
     }

// 2. Declare a private static variable to hold single instance of class
    private static Singleton2 INSTANCE = new Singleton2();

    public static Singleton2 getInstance() {
        return INSTANCE;
   }
  }

 public class SingletonCloningTest {
    public static void main(String[] args) throws Exception {
        System.out.println("Singleton Test!");
         System.out.println("Singleton Instance:" +                         +  Singleton2.getInstance());
        System.out.println("Singleton clone:"
            + Singleton2.getInstance().clone());
    }
}



 The result will:

 Singleton Test!
 Singleton Instance:[email protected]
 Singleton clone:[email protected]

Ответ 9

Вам нужно переопределить метод clone(), только если ваш singleton-класс реализует интерфейс Cloneable или класс, который реализует интерфейс Cloneable.

Ответ 10

В соответствии с моим пониманием вам не нужно реализовывать метод clone(). Причина: 1. Если вы не реализуете метод clone и интерфейс Cloneable, он будет генерировать CloneNotSupportedException. 2. Метод clone защищен, и вы не можете подклассифицировать одноэлементный класс.

Ответ 11

Переопределить метод clone() путем реализации Cloneable interface и бросить CloneNotSupportedException();

@Override
protected Object clone() throws CloneNotSupportedException {
    // directly throw Clone Not Supported Exception
    throw new CloneNotSupportedException();
}     

Подробнее об ограничении 4-х способов создания объектов в Java читайте здесь http://www.benchresources.net/singleton-design-pattern-restricting-all-4-ways-of-object-creation-in-java/