Развивая успешно заброшенную тему разбора паттернов JavaScript.
Итак Singleton, он же Одиночка.
Разберемся что нам нужно для создание такого “класса”, который будет возвращать всегда один и тот же экземпляр. Это как минимум статическая переменная instance для хранения объекта и метод возвращающий этот объект getInstance().
У нас должно получиться что-то такое:
var object1 = mySingleton.getInstance(); var object2 = mySingleton.getInstance(); console.log( object1 === object2 ); // true
В JavaScript есть 2 способа эмуляции статической переменной: используя свойство самого объекта и через замыкание. Разберем оба способа.
Создание статической переменной через свойство объекта
mySingleton.instance
Исходя из этого реализации синглтон патерна будет следующая:
var mySingleton = { getInstance: function () { if ( !mySingleton.instance ) mySingleton.instance = {x:Math.random()}; } return mySingleton.instance; } };
В данном случае {x:Math.random()} – наш экземпляр. Вместо статического задания мы можем использовать функцию:
function init(){ return {x:Math.random()}; }
var mySingleton = { getInstance: function () { if ( !mySingleton.instance ) mySingleton.instance = init(); } return mySingleton.instance; } };
Создание статической переменной используя замыкание
var mySingleton = (function(){ var instance; return { getInstance: function () { if ( !instance ) { instance = {x:Math.random()}; } return instance; } } })();
в этом варианте переменная instance хранится в замыкании созданом анонимной самовызывающейся функцией.
Публичные и приватные свойства
Публичные свойства в обоих случая добавляются довольно просто: в свойсва объекта, который возвращаем:
function init(){ return { publicMethod1: function(){ ... } publicMethod2: function(){ ... } }; }
Приватные свойсва можем сэммитировать только используя замыкание:
var mySingleton = (function(){ var instance; function privateMethod(){ //... } var privateProperty = 5; return { getInstance: function () { if ( !instance ) { instance = init(); } return instance; } } })();
Гарантия уникальности
Так как mySingleton не является функцией, то мы не можем применить к нему оператор new. и должны получать объект всегда через getInstance метод.
Вот песочница, где можно поиграться с полным примером.