Tuesday, March 25, 2014

JavaScript Design Pattern Examples

Factory

function ObjectFactory(ctor) {
  var obj = {};
  return function() {
    if(typeof ctor.prototype === 'number')
      obj.__proto__ =  Object.prototype;
    else
      obj.__proto__ =  ctor.prototype;
    var ret = ctor.apply(obj, arguments);
    return typeof ret == 'object' ? ret : obj;
  }
}
function Point(x, y) { this.x = x; this.y = y }
// The following is equivalent to: var p1 = new Point(0, 0);
var p1 = ObjectFactory(Point)(0, 0);

Singleton

var createSingletonOf = function(ctor) {
  var singleton; 
  return function() {
    return singleton || (singleton = ObjectFactory(ctor).apply(null, arguments))
  }
}
var point = createSingletonOf(Point);
var p2 = point(1,2);
var p3 = point(3,4); // p3 === p2

Observer

var Observer = (function() {
  var listeners = [];
  return {
    listen: function(callback) { listeners.push(callback) },
    trigger: function(res) { listeners.forEach(function(fn) { fn(res) }) },
    observe: function(act) { this.trigger(act()) },
  };
})();

Adaptor

// ThermometerFahr is an adapter of ThermometerCels
var ThermometerFahr = function() {
  var thermoC = new ThermometerCels();
  this.setTemperature(tempF) { thermoC.setTemperature((tempF?32)/1.8) } 
  this.getTemperature(tempF) { return thermoC.getTemperature()*1.8+32 } 
}
var thermoF = new ThermometerFahr();

Decorator

Function.prototype.bind = function (scope) { // a helper function
    var fn = this;
    return function () {
        return fn.apply(scope);
    };
}
/* MethodProfiler class */
var MethodProfiler = function(obj) {
  this.obj = obj;
  this.timers = {};
  for(var key in obj) {
    if(typeof obj[key] !== 'function') continue;
    (function(method) {
      this[method] = function() {
        this.tick(method);
        var ret = obj[method].apply(obj, arguments);
        this.log(method, this.getElapsedTime(method));
        return ret;
      }.bind(this);
    }.bind(this))(key); 
  }
};
MethodProfiler.prototype = {
  tick: function(method) {
    this.timers[method] = (new Date()).getTime();
  },
  getElapsedTime: function(method) {
    return (new Date()).getTime() - this.timers[method];
  },
  log: function(method, time) {
    console.log('Elapsed time of executing ' + method + ' is ' + time + ' ms');
  }
};

// Demonstration of usage
var test_target = { foo:function() { alert('hi there') } };
var profiler = new MethodProfiler(test_target);
// profiler is a decorator of test_target
profiler.foo();


No comments:

Post a Comment