понедельник, 3 сентября 2012 г.

Javascript. Реализация Singleton и статического класса

Реализовать статический класс в js очень просто, это будет простой объект:
var obj = {
  field: 'value',
  fnTest: function(){
    return 'res: '+ this.field;
  }
};

// Использование:
console.log( obj.field ); // 'value'
console.log( obj.fnTest() ); // 'res: value'
Если нам нужна предварительная инициализация, то добавим некий метод init, который может устанавливать значение полей объекта:
var obj = {
  field: 'value',
  options: {},
  init: function(o){
    this.options = $.extend(true, {}, o);
  },
  fnTest: function(){
     return this.field;
  }
};

// Использование:
obj.init({o:4,test:2});
console.log( obj.options ); //{o:4,test:2}
Этого функционала, в большинстве случаев, должно хватить, но бывает нужен и синглетон (Singleton): например важно иметь приватные данный и методы (статический класс полностью публичен) Один из демонстрационных вариантов реализации синглетона :
var cSingleton = (function(){
  // Class instance:
  var _instance = null;

  // Private:
  var test = 1;
  var options = {};
 
  var fnPrivate = function(){
    // some code
  }
 
  // Constructor:
  function Init(o){
    options = $.extend(true, options, o || {});
  }
  
  // Public:
  Init.prototype = {
    pub: 0,
    fnTest: function(){
       return test;
    },
    getOptions: function(){
      return options;
    }
  }

  return function(args){
    if(!_instance){
       _instance = new Init(args);
    }
    return _instance;
  }
}());

ob = new cSingleton({x:1});

console.log('1:', ob.fnTest());
console.log('opts:', ob.getOptions());

ob2 = new cSingleton({x:2});

console.log('2:', ob2.fnTest());
console.log('opts:', ob.getOptions());

// Результат:
1: 1
opts: Object { x=1}
2: 1
opts: Object { x=1}
Так мы гарантируем, что класс вернет только одно значение. Возможно это и "синтетическая" задача, но возможно кому-то и пригодиться