JavaRush /Java блог /Архив info.javarush /Шаблоны проектирования для чайников
mrserfr
33 уровень
Киев

Шаблоны проектирования для чайников

Статья из группы Архив info.javarush
Шаблоны проектирования для чайников - 1 Добрый день, Уважаемые javarushевцы! По мере изучения java, все чаще и чаще начал сталкиваться с таким понятием, как паттерны(или шаблоны) проектирования, но на просторах интернета очень мало информации на эту тему для... начинающих программистов. Проще говоря - чайников (кем я и являюсь). Я решил уделить немного времени и постараться рассказать про некоторые из них как можно более просто. Они же встречаются нам по мере продвижения на курсе javarush:
  • Singleton / Одиночка
  • Wpapper / Decorator / Обертка
  • Adapter / Адаптер
  • Strategy / Стратегия
Хочется заранее сказать, что я мог в каком-то месте ошибиться - пожалуйста, поправляйте меня, я учту и исправлю. Итак, поехали... Про шаблоны в общем //TODO Шаблоны проектирования для чайников - 2 Singleton / Одиночка Что такое? Один из порождающих паттернов, который гарантирует, что у класса есть только один экземпляр + предоставляет к нему глобальную точку доступа. Бывает потокобезопасный(может работать в многопоточной программе) и нет, с простой и отложенной инициализацией*. *Отложенная (ленивая) инициализация (англ. Lazy initialization). Приём в программировании, когда некоторая ресурсоёмкая операция (создание объекта, вычисление значения) выполняется непосредственно перед тем, как будет использован её результат. Таким образом, инициализация выполняется «по требованию», а не заблаговременно. (wiki) Зачем нужен? Синглтон нужен, чтобы точно знать, что у нас создан ОДИН объект данного класса. Примеры:
  • Ведение логов
  • Объект, который отвечает за запись логов. Нам необходим только один экземпляр, так как нужно писать лог, используя один и тот же файл.
  • Хранение настроек
  • Объект с настройками нужен только один, так как для всей программы настройки одни и те же.
Порядок действий:
  1. Cоздаем единственный экземпляр некоторого типа
  2. Предоставляем к нему доступ извне
  3. Запрещаем создание нескольких экземпляров того же типа
Есть несколько популярных реализаций данного паттерна, я рассмотрю здесь два самых простых:
  1. С ленивой инициализацией*, не синхронизированный
  2. Синхронизированный
1. С ленивой инициализацией, не синхронизированный public class NonSynchronizedSingleton { private static NonSynchronizedSingleton instance; private NonSynchronizedSingleton(){} public static NonSynchronizedSingleton getInstance(){ if(instance == null) instance = new NonSynchronizedSingleton(); return instance; } } Делаем приватным наш инстанс(объект) класса, чтобы запретить напрямую к нему обращаться private static NonSynchronizedSingleton instance; Также делаем приватным конструктор, чтобы наш синглтон и через конструктор было не создать private NonSynchronizedSingleton(){} Теперь создаем метод(работать он будет, как геттер) public static NonSynchronizedSingleton getInstance() Присваиваем ему модификатор доступа public - глобальный, то есть, теперь мы из любого места можем воспользоваться нашим singleton. В этом методе мы запрашиваем объект данного класса - если объекта еще нет, создаем его, если он уже есть, получаем его же. Обращаемся к нашему объекту мы таким образом NonSynchronizedSingleton.getInstance() Плюсы/Минусы: Данный вариант реализации хорош всем, кроме того, что он не работает в многопоточной среде, а поэтому подходит исключительно для однопоточных приложений. Почему? Потому что несколько нитей могут одновременно создать объекты данного класса. 2. Синхронизированный public class SynchronizedSingleton { private static SynchronizedSingleton instance = new SynchronizedSingleton(); private SynchronizedSingleton(){} public static SynchronizedSingleton getInstance(){ return instance; } } Описание: Создаем переменную private static SynchronizedSingleton instance = new SynchronizedSingleton(); Но делаем ее приватной, чтобы никто к ней обратиться напрямую не мог. Конструктор тоже приватный private SynchronizedSingleton(){} Ну и для работы с объектом создаем метод(геттер), который возвращает нам наш объект public static SynchronizedSingleton getInstance(){ Плюсы: Проблему многопоточности мы решили, так как static переменная инициализируется сразу же во время инициализации класса, и сколько бы нитей одновременно ни обратились, получат всегда один и тот же объект. Минусы: Теперь у нас нет отложенной инициализации (Объект instance будет создан classloader-ом во время инициализации класса) Итог: public class Test { public static void main(String[] args) { NonSynchronizedSingleton nonSynchronizedSingleton = NonSynchronizedSingleton.getInstance(); NonSynchronizedSingleton secondNonSynchronizedSingleton = NonSynchronizedSingleton.getInstance(); SynchronizedSingleton synchronizedSingleton = SynchronizedSingleton.getInstance(); SynchronizedSingleton secondSynchronizedSingleton = SynchronizedSingleton.getInstance(); System.out.println(nonSynchronizedSingleton.hashCode()); System.out.println(secondNonSynchronizedSingleton.hashCode()); System.out.println(nonSynchronizedSingleton.equals(secondNonSynchronizedSingleton)); System.out.println(synchronizedSingleton.hashCode()); System.out.println(secondSynchronizedSingleton.hashCode()); System.out.println(synchronizedSingleton.equals(secondSynchronizedSingleton)); Car car1 = new Car(); Car car2 = new Car(); System.out.println(car1.hashCode()); System.out.println(car2.hashCode()); System.out.println(car1.equals(car2)); } public static class Car {} } Пытаемся создать больше одного объекта в каждой реализации, но на выходе получаем один и тот же объект: хешкоды равны, equals возвращает true. Для примера создал класс public static class Car {} И сравнил хешкоды, equals двух объектов данного класса(уже не singleton) - хешкоды разные, equals возвращает false 1956725890 1956725890 true 356573597 356573597 true 1735600054 21685669 false Плюсы: //TODO Минусы: //TODO Шаблоны проектирования для чайников - 3 Wpapper / Decorator / Обертка Описание: //TODO Что такое Зачем нужен Примеры Порядок действий: //TODO Код: //TODO Плюсы: //TODO Минусы: //TODO Шаблоны проектирования для чайников - 4 Adapter / Адаптер Описание: //TODO Что такое Зачем нужен Примеры Порядок действий: //TODO Код: //TODO Плюсы: //TODO Минусы: //TODO Шаблоны проектирования для чайников - 5 Strategy / Стратегия Описание: //TODO Что такое Зачем нужен Примеры Порядок действий: //TODO Код: //TODO Плюсы: //TODO Минусы: //TODO При изучении тем использовал
  • http://www.programcreek.com/java-design-patterns-in-stories/
  • http://habrahabr.ru/post/103681/
  • http://habrahabr.ru/post/116577/
  • http://habrahabr.ru/post/129494/
  • http://cpp-reference.ru/patterns/catalog/
  • https://ru.wikipedia.org/wiki/%D0%9E%D1%82%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D0%B8%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F
  • http://habrahabr.ru/post/27108/
  • http://www.amse.ru/courses/cpp1/2010.03.05.html
Авторам огромное спасибо.
Комментарии (4)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Кот Уровень 26
7 июля 2023
Автор привет). Почему в статье упоминается всего две реализации синглтона(ленивая без синхронизации и жадная)? Ведь есть ленивая потокобезопасная инициализация, есть инициализация через Enum. На мой взгляд это довольно важно. P. S. Оставляю про них статьи, вдруг кому понадобится:) 1. Double-checked locking 2. Пояснение, зачем нужна Double-checked locking 3. Все реализации Singleton-a в java(в статье возможны ошибки)
14 мая 2021
Тут про паттерны посоветовали глянуть. Вдруг кому зайдёт
Aleksey Уровень 18
4 апреля 2021
а где описание остальных паттернов? Прошло столько времени, до сих пор статья не скорректирована... ((
Диана Уровень 17
5 декабря 2019
Понимаю , что статья в разработке , но про одиночку написано очень понятно , спасибо