Синглтон
Концепция синглтона
Синглтон — это класс, который можно создать только один раз. Типичными примерами синглтона являются бессостоятельные объекты или уникальные системные компоненты. Однако классы-синглтоны сложно тестировать, если они не определены как тип с помощью интерфейса и его реализации.
Способы создания синглтона
Использование публичного статического члена, являющегося финальным полем
Приватный конструктор вызывается только один раз при инициализации экземпляра Elvis, гарантируя, что он будет единственным во всей системе. Однако, используя AccessibleObject.setAccessible(), можно вызвать приватный конструктор. Этот способ модификации с помощью рефлексии можно заблокировать, выбросив исключение при создании второго объекта.
- Преимущества
- Явно указано в API, что данный класс является синглтоном.
- Лаконичность.
Предоставление статического фабричного метода в качестве public static
Помимо модификации с помощью рефлексии, этот метод также гарантирует, что экземпляр будет единственным во всей системе. Просто поле изменено на private, а возврат объекта осуществляется с помощью статического фабричного метода.
- Преимущества
- Можно изменить на не-синглтон, не изменяя API.
- Например, статический фабричный метод может возвращать разные экземпляры для каждого потока.
- При желании можно изменить на универсальный (generic) фабричный метод синглтона.
- Ссылка на метод статического фабричного метода может использоваться в качестве поставщика (supplier).
- Например, вместо Elvis::getInstance можно использовать Supplier<Elvis>.
- Можно изменить на не-синглтон, не изменяя API.
Если нет необходимости использовать вышеперечисленные преимущества, лучше использовать первый способ.
Использование перечисления (enum)
Наиболее предпочтительный способ — использование перечисления. Он более безопасен от атак с использованием рефлексии и обеспечивает более чистый код по сравнению с двумя предыдущими способами. Кроме того, как будет описано ниже, два предыдущих способа имеют недостаток: при сериализации необходимо добавлять дополнительный код.
Однако следует помнить, что синглтон, который необходимо создать, может наследовать интерфейс, но не может наследовать класс.
Что нужно учитывать при сериализации класса-синглтона
Для сериализации класса-синглтона, созданного с помощью первого или второго способа, помимо реализации Serializable, необходимо объявить все поля экземпляра как transient и переопределить метод readResolve().
Источники
- Эффективная Java
- https://catsbi.oopy.io/d7f3a636-b613-453b-91c7-655d71fda2b1
Комментарии0