Java: практические случаи для сериализации Singletons? - PullRequest
3 голосов
/ 30 марта 2012

Мы продолжаем читать о том, как использовать readResolve () для обеспечения единичности в случае сериализации Singleton.Но каковы практические случаи использования для сериализации Singleton?

EDIT: pl.примечание: вопрос о почему для сериализации Singleton, а не о том, что это безопасный способ сделать.

Ответы [ 3 ]

3 голосов
/ 30 марта 2012

Наиболее распространенным случаем является случай, когда у вас есть объект, представляющий большую структуру данных (например, дерево узлов в документе в стиле XML).

Эта структура данных может легко содержать одноэлементные значения (например, одноэлементные экземпляры, которые представляют тип данных определенного атрибута, присоединенного к узлу в дереве). Многие разные узлы в дереве могут указывать на одно и то же значение синглтона.

Есть много обстоятельств, когда вы можете захотеть сериализовать такую ​​структуру данных, например, отправка копии объекта по сети. В этом случае вам также необходимо сериализовать значения синглтона.

Но затем, когда вы снова читаете структуру данных, вы хотите использовать существующее значение синглтона, а не вновь созданный экземпляр. Вот почему вам нужно readResolve()

2 голосов
/ 30 марта 2012

Джошуа Блох Effective Java (2nd Edition) предлагают использовать Enum в качестве синглтона. Он всегда создается виртуальной машиной, и невозможно (или сложно) создать второй экземпляр синглтона.

Для обычного синглтона вы всегда можете взломать систему, см .:

Шаблон синглтона

Hot Spot:
Multithreading - A special care should be taken when singleton has to be used in a multithreading application.
Serialization - When Singletons are implementing Serializable interface they have to implement readResolve method in order to avoid having 2 different objects.
Classloaders - If the Singleton class is loaded by 2 different class loaders we'll have 2 different classes, one for each class loader. 
Global Access Point represented by the class name - The singleton instance is obtained using the class name. At the first view this is an easy way to access it, but it is not very flexible. If we need to replace the Sigleton class, all the references in the code should be changed accordinglly.
1 голос
/ 30 марта 2012

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

interface StringSink extends Serializable { void dump(String s); }

class MultiDumper implements Serializable {
    private final StringSink sink;
    public MultiDumper(StringSink sink){ this.sink = sink; }
    void doSomeStuff(Collection<String> strings){
        for (String s : strings) sink.dump(s);
    }
}

Теперь, скажем, нам нужен StringSink, который выводит строки встандартный вывод.Поскольку есть только один стандартный вывод, мы могли бы также сделать его синглтоном:

/** Beware: Not good for serializing! */
class StdoutStringSink {
    public static final StdoutStringSink INSTANCE = new StdoutStringSink();
    private StdoutStringSink(){}
    @Override
    public void dump(String s){ System.out.println(s); }
}

И мы используем его так:

MultiDumper dumper = new MultiDumper(StdoutStringSink.INSTANCE);

Если вы хотите сериализовать, а затем десериализовать этоdumper, в вашей программе будет два StdoutStringSink экземпляра.

...