Развивая успешно заброшенную тему разбора паттернов 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 метод.
Вот песочница, где можно поиграться с полным примером.