Сегодня начнем тематику паттернов проектирования. Паттерны проектирования - это описание некоторых проблем, возникающих во время объектно-ориентированного проектирования, а также способов их решения (как практических, так и теоретических). Говоря иначе - это примеры правильных подходов к решению классических задач проектирования.
Хотелось бы начать с самого распространенного паттерна - Singleton (Одиночка).
Хотелось бы начать с самого распространенного паттерна - Singleton (Одиночка).
Задача: Ограничить количество экземпляров некоторого класса.
Реализация:
- Ленивый / Lazy initialization
- Активный / Eager initialization
Если программа будет всегда нужна, например, или если стоимость создания экземпляра не слишком велика по времени и ресурсам, программист может переключиться на активную инициализацию, которая всегда создает экземпляр:
Далее разберем нашу композицию по ноткам:
Конструктор класса необходимо объявить с модификатором видимости private. Это предотвратит создание экземпляров класса как с помощью класса Singleton, так и с помощью его наследников. В связи с этим к объявлению класса смело можно дописать модификатор final.
Метод getInstance() создаст ровно один экземпляр класса Singleton. Этот метод объявлен как synchronized. Сделано это вот почему. В многопоточных программах при одновременном вызове метода getInstance() из нескольких потоков можно создать несколько экземпляров класса Singleton. А должен остаться только один!
От модификатора synchronized можно избавиться. Для этого _instance нужно проинициализировать:
Но использование ленивой(поздней)инициализации (lazy initialization) предпочтительнее в случае, если создание экземпляра класса занимает много времени.
А теперь перейдем к применению, зачем нужен Singleton:
Мне приходится чаще всего использовать этот паттерн при работе с конфигурацией. Иногда конфигурацию программы удобно хранить в файле. Допустим, это будет простой текстовый файл “props.txt” со строками типа “ключ=значение”. Нам нужно гарантировать, что конфигурация в программе будет в единственном экземпляре. Вторую мы бы и так не создали, но нужно запретить это делать пользователю класса. Итак,
Теперь для работы с конфигурацией можно использовать конструкцию вида:
Если имена свойств в “props.txt” меняться не будут, можно описать их в классе таким образом:
а значения получать так:
На том пока все :)
- Ленивый / Lazy initialization
public class Singleton { private static Singleton instance = null; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- Активный / Eager initialization
Если программа будет всегда нужна, например, или если стоимость создания экземпляра не слишком велика по времени и ресурсам, программист может переключиться на активную инициализацию, которая всегда создает экземпляр:
public class Singleton { private static Singleton _instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return _instance; } }
Далее разберем нашу композицию по ноткам:
Конструктор класса необходимо объявить с модификатором видимости private. Это предотвратит создание экземпляров класса как с помощью класса Singleton, так и с помощью его наследников. В связи с этим к объявлению класса смело можно дописать модификатор final.
Метод getInstance() создаст ровно один экземпляр класса Singleton. Этот метод объявлен как synchronized. Сделано это вот почему. В многопоточных программах при одновременном вызове метода getInstance() из нескольких потоков можно создать несколько экземпляров класса Singleton. А должен остаться только один!
От модификатора synchronized можно избавиться. Для этого _instance нужно проинициализировать:
private static final Singleton _instance = new Singleton(),а в методе getInstance() удалить "if".
Но использование ленивой(поздней)инициализации (lazy initialization) предпочтительнее в случае, если создание экземпляра класса занимает много времени.
А теперь перейдем к применению, зачем нужен Singleton:
Мне приходится чаще всего использовать этот паттерн при работе с конфигурацией. Иногда конфигурацию программы удобно хранить в файле. Допустим, это будет простой текстовый файл “props.txt” со строками типа “ключ=значение”. Нам нужно гарантировать, что конфигурация в программе будет в единственном экземпляре. Вторую мы бы и так не создали, но нужно запретить это делать пользователю класса. Итак,
import java.util.*; import java.io.*; public class Configuration { private static Configuration _instance = null; private Properties props = null; private Configuration() { props = new Properties(); try { FileInputStream fis = new FileInputStream( new File(“props.txt”)); props.load(fis); } catch (Exception e) { // обработайте ошибку чтения конфигурации } } public synchronized static Configuration getInstance() { if (_instance == null) _instance = new Configuration(); return _instance; } // получить значение свойства по имени public synchronized String getProperty(String key) { String value = null; if (props.containsKey(key)) value = (String) props.get(key); else { // сообщите о том, что свойство не найдено } return value; } }
Теперь для работы с конфигурацией можно использовать конструкцию вида:
String propValue = Configuration.getInstance() .getProperty(propKey);
Если имена свойств в “props.txt” меняться не будут, можно описать их в классе таким образом:
public static final String PROP_KEY = “propKey”,
а значения получать так:
String propValue = Configuration.getInstance(). getProperty(Configuration.PROP_KEY).Так же Singleton частенько применяется для коннекта к базам данных...
На том пока все :)
Комментариев нет:
Отправить комментарий