JavaScript设计模式

模块模式The Module Pattern:


( function( window, undefined ) {

// normally variables & functions start with a lowercase letter but with modules, that is not the case.
// The general tradition is to start them with a capital letter instead.
//注意开头大小写,这里是大写。
function MyModule() {

// `this` refers to the instance of `MyModule` when created
this.myMethod = function myMethod() {
alert( 'my method' );
};

// note that we still use a function declaration even when using a function expression.
// for more information on why, check out: http://kangax.github.io/nfe/
this.myOtherMethod = function myOtherMethod() {
alert( 'my other method' );
};

}

// expose access to the constructor
window.MyModule = MyModule;

} )( window );

// example usage
var myModule = new MyModule();
myModule.myMethod(); // alerts "my method"
myModule.myOtherMethod(); // alerts "my other method"

下面代码使用共享空间性能更好些:


var MyModule = ( function( window, undefined ) {

// this object is used to store private variables and methods across multiple instantiations
//这里可以跨多个实例保存一些私有变量和方法
var privates = {};

function MyModule() {

this.myMethod = function myMethod() {
alert( 'my method' );
};

this.myOtherMethod = function myOtherMethod() {
alert( 'my other method' );
};

}

return MyModule;

} )( window );

// example usage
var myMod = new MyModule();
myMod.myMethod(); // alerts "my method"
myMod.myOtherMethod(); // alerts "my other method"

待续.

揭示式模块模式Revealing Module Pattern

类似于模块模式,不过将模块的方法和变量变为私有的,只有在需要显式暴露时才揭示,主要焦点是方法上:



var MyModule = ( function( window, undefined ) {

function myMethod() {
alert( 'my method' );
}

function myOtherMethod() {
alert( 'my other method' );
}

// explicitly return public methods when this object is instantiated
return {
someMethod : myMethod,
someOtherMethod : myOtherMethod
};

} )( window );

// example usage
MyModule.myMethod();
// undefined
MyModule.myOtherMethod();
// undefined
MyModule.someMethod();
// alerts "my method"
MyModule.someOtherMethod();
// alerts "my other method"

代码中myMethod和myOtherMethod两个方法是私有的,不能被外部方法,只有通过专门的someMethod和someOtherMethod才可以。

单例模式Singleton Pattern

好处是减少内存泄漏。



var mySingleton = ( function( window, undefined ) {

var instance = null;

// revealing module pattern that handles initialization of our new module
function initializeNewModule() {

function myMethod() {
alert( 'my method' );
}

function myOtherMethod() {
alert( 'my other method' );
}

return {
someMethod : myMethod,
someOtherMethod : myOtherMethod
};

}

// handles the prevention of additional instantiations
function getInstance() {
if( ! instance ) {
instance = new initializeNewModule();
}
return instance;
}

return {
getInstance : getInstance
};

} )( window );

// example usage
mySingleton.getInstance().someMethod();
// alerts "my method"
mySingleton.getInstance().someOtherMethod();
// alerts "my other method"

观察者模式observer pattern



// build the Subject base class 定义一个被的观察subject
var Subject = ( function( window, undefined ) {

function Subject() {
this._list = [];
}

// this method will handle adding observers to the internal list
Subject.prototype.observe = function observeObject( obj ) {
console.log( 'added new observer' );
this._list.push( obj );
};

Subject.prototype.unobserve = function unobserveObject( obj ) {
for( var i = 0, len = this._list.length; i < len; i++ ) {
if( this._list[ i ] === obj ) {
this._list.splice( i, 1 );
console.log( 'removed existing observer' );
return true;
}
}
return false;
};

Subject.prototype.notify = function notifyObservers() {
var args = Array.prototype.slice.call( arguments, 0 );
for( var i = 0, len = this._list.length; i < len; i++ ) {
this._list[ i ].update.apply( null, args );
}
};

return Subject;

} )( window );

// setup an object that fetchs stocks
function StockGrabber() {

var subject = new Subject();

this.addObserver = function addObserver( newObserver ) {
subject.observe( newObserver );
};

this.removeObserver = function removeObserver( deleteObserver ) {
subject.unobserve( deleteObserver );
};

this.fetchStocks = function fetchStocks() {
// fake fetching the stocks
var stocks = {
aapl : 167.00,
goog : 243.67,
msft : 99.34
};

// notify our observers of the stock change
subject.notify( stocks );
};

}

// define a couple of different observers 定义观察者
var StockUpdaterComponent = {
update : function() {
console.log( '
"update" called on StockUpdater with: ', arguments );
}
};
var StockChartsComponent = {
update : function() {
console.log( '
"update" called on StockCharts with: ', arguments );
}
};

// example usage
var stockApp = new StockGrabber();
stockApp.addObserver( StockUpdaterComponent );
stockApp.fetchStocks();
// console logs: "update" called on StockUpdater with...
stockApp.addObserver( StockChartsComponent );
stockApp.fetchStocks();
// console logs: "update" called on StockUpdater with... "update" called on StockCarts with...
stockApp.removeObserver( StockUpdaterComponent );
stockApp.fetchStocks();
// console logs: "update" called on StockCharts with...
stockApp.removeObserver( StockChartsComponent );
stockApp.fetchStocks();
// does nothing; no observers

中介者模式Mediator Pattern

中间者模式与观察者模式主要区别是在中间者对象中封装了两者通讯交互行为,观察者和被观察者在观察模式中通讯交互是直接在两者之中进行进行的。


var Mediator = ( function( window, undefined ) {

function Mediator() {
this._topics = {};
}

Mediator.prototype.subscribe = function mediatorSubscribe( topic, callback ) {
if( ! this._topics.hasOwnProperty( topic ) ) {
this._topics[ topic ] = [];
}

this._topics[ topic ].push( callback );
return true;
};

Mediator.prototype.unsubscribe = function mediatorUnsubscrive( topic, callback ) {
if( ! this._topics.hasOwnProperty( topic ) ) {
return false;
}

for( var i = 0, len = this._topics[ topic ].length; i < len; i++ ) {
if( this._topics[ topic ][ i ] === callback ) {
this._topics[ topic ].splice( i, 1 );
return true;
}
}

return false;
};

Mediator.prototype.publish = function mediatorPublish() {
var args = Array.prototype.slice.call( arguments );
var topic = args.shift();

if( ! this._topics.hasOwnProperty( topic ) ) {
return false;
}

for( var i = 0, len = this._topics[ topic ].length; i < len; i++ ) {
this._topics[ topic ][ i ].apply( undefined, args );
}
return true;
};

return Mediator;

} )( window );

// example subscriber function
var Subscriber = function ExampleSubscriber( myVariable ) {
console.log( myVariable );
};

// example usages
var myMediator = new Mediator();
myMediator.subscribe( 'some event', Subscriber );
myMediator.publish( 'some event', 'foo bar' );
// console logs "foo bar"

Prototype Pattern原型模式

原型模式类似克隆模式。



// build our blueprint object
var MyBluePrint = function MyBluePrintObject() {

this.someFunction = function someFunction() {
alert( 'some function' );
};

this.someOtherFunction = function someOtherFunction() {
alert( 'some other function' );
};

this.showMyName = function showMyName() {
alert( this.name );
};

};

function MyObject() {
this.name = 'testing';
}
MyObject.prototype = new MyBluePrint();

// example usage
var testObject = new MyObject();
testObject.someFunction();
// alerts "some function"
testObject.someOtherFunction();
// alerts "some other function"
testObject.showMyName();
// alerts "testing"