Мои Конспекты
Главная | Обратная связь


Автомобили
Астрономия
Биология
География
Дом и сад
Другие языки
Другое
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Металлургия
Механика
Образование
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Туризм
Физика
Философия
Финансы
Химия
Черчение
Экология
Экономика
Электроника

Свойство синглтона обеспечивайте закрытым конструктором



Сuнглтон (singleton) - это класс, для которого экземпляр создается только один раз [Саmmа95, стр.127]. Синглтоны обычно представляют некоторые компоненты системы, которые действительно являются уникальными, например видеодисплей или файловая система.

Для реализации синглтонов используются два подхода. Оба они основаны на создании закрытого (private) конструктора и открытого (public) статического члена, который обеспечивает клиентам доступ к единственному экземпляру этого класса. В первом варианте открытый статический член является полем типа final:

// Синглтон с полем типа final

public class Elvis {

public static final Elvis INSTANCE = new Elvis();

private Elvis() {

// ...

}

 

// ... // Остальное опущено

 

public static void main(String[] args) {

System.out.println(Elvis.INSTANCE);

}

}

 

Закрытый конструктор вызывается только один раз для инициализации поля Elvis.INSTANCE. Отсутствие открытых или защищенных конструкторов гарантирует "вселенную с одним Elvis": после инициализации класса Elvis будет существовать ровно один экземпляр Elvis - не больше и не меньше. И клиент не может ничего с этим поделать.

Во втором варианте вместо открытого статического поля типа final создается открытый статический метод генерации:

// Синглтон со статическим методом генерации

import java.io.*;

public class Elvis {

public static final Elvis INSTANCE = new Elvis();

 

private Elvis() {

// ...

}

// ... // Остальное опущено

}

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

Основное преимущество первого подхода заключается в том, что из декларации членов, составляющих класс, понятно, что этот класс является синглтоном: открытое статическое поле имеет тип fina!, а потому оно всегда будет содержать ссылку на один и тот же объект. Первый вариант, по сравнению со вторым, может также иметь неко­торое преимущество в производительности. Однако хорошая реализация JVM должна свести это преимущество к минимуму благодаря встраиванию (in!ining) вызовов для статического метода генерации во втором варианте.

Основное преимущество второго подхода заключается в том, что он позволяет вам отказаться от решения сделать класс синглтоном, не меняя при этом его АР!. Статический метод генерации для синглтона возвращает единственный экземпляр этого класса, однако это можно легко изменить и возвращать, скажем, свой уникаль­ный экземпляр для каждого, потока, обращающегося к этому методу.

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

Если требуется сделать класс синглтона сериализуемым (см. главу 10), недоста­точно добавить к его декларации implements Serializable. Чтобы дать синглтону нужные гарантии, необходимо также создать метод readResolve (статья 57). В противном случае каждая десериализация сериализованного экземпляра будет приводить к созданию нового экземпляра, что в нашем примере станет причиной

 

 

обнаружения ложных Elvis. Во избежание этого добавьте в класс Elvis следующий метод readResolve:

// Метод readResolve, сохраняющий свойство синглтона

private Object readResolve() throws ObjectStreamException {

/*

* Возвращает единственный истинный Elvis и позволяет

* сборщику мусора разобраться с Еlvis-самозванцем

*/

return INSTANCE;

}

 

public static void main(String[] args) {

System.out.println(Elvis.INSTANCE);

}

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