Шаблон синглтон имеет следующие характеристики:
1. Одноэлементный класс может иметь только один экземпляр.
2. Одноэлементный класс должен создать свой собственный уникальный экземпляр.
3. Класс-одиночка должен предоставить этот экземпляр всем остальным объектам.
Шаблон синглтон гарантирует, что существует только один экземпляр класса, он создает свой экземпляр и предоставляет этот экземпляр всей системе. В компьютерных системах пулы потоков, кэши, объекты журналов, диалоговые окна, принтеры и объекты драйверов видеокарт часто проектируются как одиночные. Все эти приложения в той или иной степени обладают функциями менеджеров ресурсов. На каждом компьютере может быть несколько принтеров, но диспетчер очереди печати может быть только один, чтобы предотвратить одновременный вывод на принтер двух заданий печати. Каждый компьютер может иметь несколько портов связи, и система должна централизованно управлять этими портами связи, чтобы предотвратить одновременный вызов одного порта связи двумя запросами. Короче говоря, цель выбора одноэлементного режима — избежать несогласованных состояний и долгосрочной политики.
Во-первых, давайте посмотрим на классическую реализацию синглтона.
Скопируйте код кода следующим образом:
публичный класс Синглтон {
частный статический Singleton uniqueInstance = null;
частный синглтон() {
// Существует только для того, чтобы отменить создание экземпляра.
}
public static Singleton getInstance() { if (uniqueInstance == null) {
uniqueInstance = новый синглтон ();
}
вернуть уникальный экземпляр;
}
// Другие методы...
}
Singleton позволяет избежать внешнего создания экземпляра класса, ограничивая метод создания частным. В пределах одной виртуальной машины доступ к единственному экземпляру Singleton возможен только через метод getInstance(). (На самом деле, можно создать экземпляр класса с помощью частного конструктора с помощью механизма отражения Java, который по сути сделает недействительными все реализации Java Singleton. Этот вопрос здесь обсуждаться не будет. Давайте представим, что механизма отражения не существует. .)
Однако приведенная выше реализация не учитывает проблемы безопасности потоков. Так называемая потокобезопасность означает: если в процессе, в котором находится ваш код, одновременно выполняется несколько потоков, эти потоки могут запускать этот код одновременно. Если результаты каждого запуска такие же, как и при однопоточном запуске, а значения других переменных такие же, как и ожидалось, он является потокобезопасным. Другими словами: интерфейс, предоставляемый классом или программой, является атомарной операцией для потоков или переключение между несколькими потоками не вызовет неоднозначности в результатах выполнения интерфейса, а это значит, что нам не нужно учитывать вопросы синхронизации. Очевидно, что приведенная выше реализация не отвечает требованиям потокобезопасности, и в параллельной среде могут появиться несколько экземпляров Singleton.
Скопируйте код кода следующим образом:
//Одноэлементный класс в стиле Hungry. Экземпляр создается сам по себе при инициализации класса.
общественный класс Singleton1 {
//Частный конструктор по умолчанию
частный синглтон1() {}
//Уже создан экземпляр
частный статический окончательный Singleton1 сингл = новый Singleton1();
//статический фабричный метод
общественный статический Singleton1 getInstance() {
возврат сингла;
}
}
//Ленивый одноэлементный класс, создаем экземпляр при первом вызове.
общественный класс Singleton2 {
//Частный конструктор по умолчанию
частный синглтон2() {}
//Обратите внимание, здесь нет финала
частный статический Singleton2 Single = null;
//статический фабричный метод
общедоступный синхронизированный статический Singleton2 getInstance() {
если (одиночный == ноль) {
одиночный = новый Singleton2();
}
возврат сингла;
}
}