Шаблон Singleton: ограничить количество экземпляров класса только один раз, класс имеет только один экземпляр и предоставить глобальную точку доступа для доступа к нему.
Паттерн Singleton — это тип творческого паттерна проектирования. Для сценариев, где глобально требуется только один объект, например пул потоков, глобальный кеш, объект окна и т. д.
Особенности режима
- класс имеет только один экземпляр
- Экземпляр доступен глобально
- Самосоздание (активное создание экземпляров)
- Отложенная инициализация, т.е. отложенное выполнение (отличие от статических классов/объектов)
JavaScript — это неформальный объектно-ориентированный язык без определений классов. Для одноэлементного шаблона требуется «уникальный» и «глобально доступный» объект, который похож на глобальный объект в JavaScript, просто чтобы соответствовать двум характеристикам одноэлементного шаблона: «уникальный» и «глобально доступный». Хотя это не формальный одноэлементный шаблон, нельзя отрицать, что он обладает характеристиками одноэлементного шаблона.
// 全局对象
var globaObj = {};
Использование глобальных переменных имеет следующие проблемы:
- Загрязнение пространства имен (конфликт имен переменных)
- Неудобно контролировать во время обслуживания (легко случайно накрыть)
Решение проблемы компрометации глобальной переменной:
- использовать пространство имен
- Замыкания инкапсулируют закрытые переменные (используя область действия функции)
- ES6 константа/символ
Хотя глобальные переменные могут реализовывать синглтоны, из-за их собственных проблем не рекомендуется использовать их в качестве шаблона синглтона в реальных проектах, особенно в приложениях средних и крупных проектов.Поддержание глобальных переменных следует рассматривать как затраты.
реализация шаблона
Метод реализации: использовать переменную для хранения объекта экземпляра класса (значение изначально
null/undefined). При создании экземпляра класса оценивается, существует ли объект экземпляра класса, и экземпляр возвращается, если он существует.Если он не существует, экземпляр класса создается и возвращается. Многократный вызов метода создания экземпляра класса возвращает один и тот же объект экземпляра.
«Простая версия» синглтон-шаблона:
let Singleton = function(name) {
this.name = name;
this.instance = null;
}
Singleton.prototype.getName = function() {
console.log(this.name);
}
Singleton.getInstance = function(name) {
if (this.instance) {
return this.instance;
}
return this.instance = new Singleton(name);
}
let Winner = Singleton.getInstance('Winner');
let Looser = Singleton.getInstance('Looser');
console.log(Winner === Looser); // true
console.log(Winner.getName()); // 'Winner'
console.log(Looser.getName()); // 'Winner'
Кодекс определяетSingletonФункции, функции являются "первоклассными гражданами" в JavaScript и могут определять для них методы свойств. Таким образом, мы можем использовать функциюSingletonопределитьgetInstance()методы для управления синглтонами и создания объектов экземпляра возвращаемого класса вместо передачи традиционныхnewоператор для создания объектов экземпляра класса.
this.instanceСохраните созданный объект экземпляра и оценивайте каждый раз, когда получен созданный объект экземпляра.this.instanceЕсть ли объект экземпляра, вернуть, если есть, создать и обновить, если нетthis.instanceзначение, поэтому независимо от того, сколько раз оно вызываетсяgetInstance(), в конечном итоге вернет то же самоеSingletonобъект экземпляра класса.
Существует проблема:
- Недостаточно «прозрачный» для использования
newЧтобы создать экземпляр класса, вам необходимо ограничить измененный режим вызова:Singleton.getInstance(...); - Операция управления синглтоном сопряжена с операцией создания объекта и функционального кода, что не соответствует «принципу единой ответственности».
"Прозрачный" одноэлементный шаблон:
Реализовать одноэлементный шаблон "прозрачная версия", предназначенный для решения: унифицированного использованияnewоператор для получения одноэлементного объекта вместоSingleton.getInstance(...).
let CreateSingleton = (function(){
let instance;
return function(name) {
if (instance) {
return instance;
}
this.name = name;
return instance = this;
}
})();
CreateSingleton.prototype.getName = function() {
console.log(this.name);
}
let Winner = new CreateSingleton('Winner');
let Looser = new CreateSingleton('Looser');
console.log(Winner === Looser); // true
console.log(Winner.getName()); // 'Winner'
console.log(Looser.getName()); // 'Winner'
Одноэлементный шаблон "прозрачная версия" решает проблему недостаточной "прозрачности", и мы можем использоватьnewоператор для создания объектов-экземпляров.
Одноэлементный шаблон «прокси-версия»:
С помощью формы «прокси» цель состоит в том, чтобы решить: отделить одноэлементную операцию управления от операции создания объекта для достижения меньшего деления детализации в соответствии с «принципом единой ответственности».
let ProxyCreateSingleton = (function(){
let instance;
return function(name) {
// 代理函数仅作管控单例
if (instance) {
return instance;
}
return instance = new Singleton(name);
}
})();
// 独立的Singleton类,处理对象实例
let Singleton = function(name) {
this.name = name;
}
Singleton.prototype.getName = function() {
console.log(this.name);
}
let Winner = new PeozyCreateSingleton('Winner');
let Looser = new PeozyCreateSingleton('Looser');
console.log(Winner === Looser); // true
console.log(Winner.getName()); // 'Winner'
console.log(Looser.getName()); // 'Winner'
Ленивый одноэлементный шаблон
Ленивый синглтон, предназначенный для решения: создавать объекты экземпляра класса только при необходимости. Фронтенд-разработчикам не привыкать к ленивой оптимизации производительности загрузки. Ленивые синглтоны также решают проблему «загрузки по требованию».
Требование: Всплывающее окно страницы запрашивает, несколько вызовов, есть только один объект всплывающего окна, но отображаемое информационное содержание отличается.
Чтобы разработать такой глобальный всплывающий объект, мы можем применить шаблон singleton. Чтобы повысить его производительность, мы можем заставить его генерировать экземпляры и создавать узлы DOM, когда нам нужно их вызывать.
let getSingleton = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments)); // 确定this上下文并传递参数
}
}
let createAlertMessage = function(html) {
var div = document.createElement('div');
div.innerHTML = html;
div.style.display = 'none';
document.body.appendChild(div);
return div;
}
let createSingleAlertMessage = getSingleton(createAlertMessage);
document.body.addEventListener('click', function(){
// 多次点击只会产生一个弹窗
let alertMessage = createSingleAlertMessage('您的知识需要付费充值!');
alertMessage.style.display = 'block';
})
В коде продемонстрирован общий метод создания "ленивого синглтона", если вам нужноcreateLoginLayerокно входа,createFrameКаркасная коробка, можно назватьgetSingleton(...)Метод для создания соответствующего объекта экземпляра.
Применимая сцена
«Характеристики одноэлементного шаблона, предназначенного для решения: поддерживать глобальный экземпляр объекта».
- Ссылки на сторонние библиотеки (несколько ссылок будут использовать только одну ссылку на библиотеку, например jQuery)
- Всплывающее окно (окно входа в систему, окно информационного продвижения)
- корзина (одна корзина на пользователя)
- Хранилище управления глобальным состоянием (Vuex/Redux)
Когда в проект вводится сторонняя библиотека, когда файл библиотеки загружается повторно, глобально создается только один объект библиотеки, напримерjQuery,lodash,moment..., на самом деле, их концепция реализации также является своего рода приложением шаблона singleton:
// 引入代码库 libs(库别名)
if (window.libs != null) {
return window.libs; // 直接返回
} else {
window.libs = '...'; // 初始化
}
Преимущества и недостатки
- Преимущества: применимо к одному объекту, генерируется только один экземпляр объекта, что позволяет избежать частого создания и уничтожения экземпляров и сократить использование памяти.
- Недостатки: Не подходит для динамически расширяющихся объектов или сценариев, в которых необходимо создать несколько похожих объектов.
СОВЕТЫ: В многопоточных языках программирования одноэлементный режим связан с проблемой блокировок синхронизации. Поскольку JavaScript является однопоточным языком программирования, на эту проблему можно пока не обращать внимания.
Справочная статья
- Шаблоны проектирования JavaScript
- Шаблоны проектирования JavaScript и практика разработки
- «Объяснение и применение системы шаблонов проектирования JavaScript»
Эта статья была впервые опубликована на Github, с нетерпением жду Star!GitHub.com/Zen GL поможет вам…
Автор: во имя радости Эта статья является оригинальной, и любые неуместные места приветствуются. Пожалуйста, указывайте источник при перепечатке.