it-swarm.com.ru

Шаблон дизайна Singleton и предотвращение клонирования

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

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

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

23
shrini1000

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


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

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

24
Matt Ball

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

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

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

7
Gourabp

Приведенный ниже код предназначен для предотвращения клонирования одноэлементного класса. Переопределите метод 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();
        }
    }

}
3
Rahul Tripathi

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

2
user2103311

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

public Object clone() {

return singletoneObject;

}
2
user3020398

См. https://stackoverflow.com/a/71399/385478 , чтобы узнать о наиболее безопасном способе применения шаблона Singleton. По сути, сделайте ваш Singleton enum, а не class, с одним значением INSTANCE.

2
Graham Borland

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

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

2
aleroot

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

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]
1
hitesh141

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

0
Anirban B

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

0
prageeth