SlideShare a Scribd company logo
小谈Javascript设计模式鲁超伍|Adamhttp://adamlu.com/http://twitter.com/adamlu
为什么要使用设计模式设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
设计模式(Design Patterns)工厂(Factory)模式单体(Singleton)模式装饰者(Decorator)模式桥接(Bridge)模式适配器(Adapter)模式观察者(Observer)模式门面(Façade)模式策略(Strategy)模式命令(Command)模式职责链(Chain Of Responsibility)模式组合(Composite)模式享元(Flyweight)模式……
工厂(Factory)模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
Factory-EXPif (typeofXMLHttpRequest != "undefined") {    return new XMLHttpRequest();} else if (typeofwindow.ActiveXObject != "undefined") {    return new ActiveXObject("MSXML2.XMLHttp");}function XMLHttpFactory() {}XMLHttpFactory.createXMLHttp = function () {    if (typeofXMLHttpRequest != "undefined") {        return new XMLHttpRequest();    } else if (typeofwindow.ActiveXObject != "undefined") {        return new ActiveXObject("MSXML2.XMLHttp");    }} varxmlhttp=XMLHttpFactory.createXMLHttp();
单体(Singleton)模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Singleton-EXPUserAgent = function UserAgent() { var u = navigator.userAgent, d = document;    this.ie = typeofd.all != "undefined";    this.ns4 = typeofd.layers != "undefined";this.dom = typeofd.getElementById != "undefined";this.safari = /Safari/.test(u);this.moz = /Gecko/.test(u) && !this.safari;this.mie = this.ie && /Mac/.test(u);    this.win9x = /Win9/.test(u) || /Windows 9/.test(u);    this.o7 = /Opera 7/.test(u);this.supported = (typeofd.write != "undefined")                      && (this.ie || this.ns4 || this.dom);};
Singleton-EXPua = new function UserAgent() {var u = navigator.userAgent, d = document;    this.ie = typeofd.all != "undefined";    this.ns4 = typeofd.layers != "undefined";this.dom = typeofd.getElementById != "undefined";this.safari = /Safari/.test(u);this.moz = /Gecko/.test(u) && !this.safari;this.mie = this.ie && /Mac/.test(u);    this.win9x = /Win9/.test(u) || /Windows 9/.test(u);    this.o7 = /Opera 7/.test(u);this.supported = (typeofd.write != "undefined")                      && (this.ie || this.ns4 || this.dom);};
装饰者(Decorator)模式动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。
Decorator-EXP// Create a Name Space  myText = { };  myText.Decorators = { };  // Core base class   myText.Core = function( myString ) {this.show = function( ) {   return myString;      };  }  // First Decorator, to add quesCon mark to string  myText.Decorators.addQuestionMark = function ( myString ) {this.show = function( ){   return myString.show( ) + '?'; };    }  //Second Decorator, to make string Italics  myText.Decorators.makeItalic = functioon( myString ) {this.show = function(){   return "<i>" + myString.show( ) + "</i>";      };  }
Decorator-EXP//Third Decorator, to make first character of sentence caps  myText.Decorators.upperCaseFirstChar = function( myString ) {this.show = function( ){ varstr = myString.show( ); varucf = str.charAt(0).toUpperCase( );return ucf + str.substr( 1, str.length – 1 );     };  }  // Set up the core String   vartheString = new myText.Core( “this is a sample test string” );  // Decorate the string with Decorators  theString = new myText.Decorator.upperCaseFirstChar( theString );  theString = new myText.Decorator.addQuestionMark( theString );  theString = new myText.Decorator.makeItalic( theString );   theString.show();
桥接(Bridge)模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。
Bridge-EXPaddEvent(element, 'click', getBeerById);function getBeerById(e) {var id = this.id;asyncRequest('GET', 'beer.uri?id=' + id, function(resp) {// Callback response.console.log('Requested Beer: ' + resp.responseText);});}
Bridge-EXPfunction getBeerById(id, callback) {// Make request for beer by ID, then return the beer data.asyncRequest('GET', 'beer.uri?id=' + id, function(resp) {// callback responsecallback(resp.responseText);});}addEvent(element, 'click', getBeerByIdBridge);function getBeerByIdBridge (e) {getBeerById(this.id, function(beer) {console.log('Requested Beer: '+beer);});}
适配器(Adapter)模式将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Adapter-EXPfunction $(){};function YAHOO.util.Dom.get=function(el){};function prototypeToYuiAdapter(){      return YAHOO.util.Dom.get(arguments);    }function YUIToPrototypeAdapter(el) { return $.apply(window, el); }$ = prototypeToYuiAdapter;YAHOO.util.Dom.get = YUIToPrototypeAdapter;
观察者(Observer)模式定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
Observer-EXP// The Observer Object – One who super sees all the print operations function printManager( ) { var queue = [ ]; // The attach method this.addJob = function(name, job) { queue.push( { ”name” : name, "job” : job } ); } // The detach method this.removeJob = function(job) { var _queue = [ ]; for(var i in queue) { if(queue[ i ].job == job) continue; else _queue.push( queue[ i ] ); } queue = _queue; } // The notify method this.doPrint = function( item ) { for ( var i in queue ) { queue[ i ].job.call( this, item );}} }
Observer-EXPvar p = new printManager(); // Publishers are in charge of "publishing” function printWithItalics( str ) { // The callback function – the print job alert( “<i>” + str + “</i>” ); } //Once subscribers are notified their callback functions are invokedp.addJob( "italics", printWithItalics); // Notify the observer about a state change p.doPrint("this is a test");
门面(Facade)模式子系统中的一组接口提供一个一致的界面, 门面模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
Facade-EXPfunction IEBrowser()  {this.hello=function(){alert(”IE browser”);}}function NonIEBrowser()  (this.hello =function(){alert(“NonIE browser”);}}var Facade={};Facade.hello=function(){var browser;if(window.ActiveXObject)  browser=new IEBrowser();else browser=new NonIEBrowser();Browser.hello(););
策略(Strategy)模式定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
Strategy-EXPvar Button = function(submit_func, label) {this.label = label; 	return { on_submit : function(numbers) { 			return submit_func(numbers);		} 	};};var numbers = [1,2,3,4,5,6,7,8,9];
Strategy-EXPvar sum = function(n) { var sum = 0; 	for ( var a in n ) { 		sum = sum + n[a]; 	} 	return sum;}; var a = new Button(sum, "Add numbers");var b = new Button(function(numbers) { 			return numbers.join(','); 		}, "test2");a.on_submit(numbers);b.on_submit(numbers);
命令(Command)模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
Command-EXPvar Calculator={// additionadd: function(x,y) {return x+y;},// subtractionsubstract: function(x, y) {return x-y;},// multiplicationmultiply: function(x, y) {return x*y;},// divisiondivide: function(x, y) {return x/y;},};
Command-EXPCalculator.calc=function(command)  {return Calculator[command.type](command.opl,command.op2);};Calculator.calc({type: "add",opl:1,op2:1});Calculator.calc({type: "Substract",opl:6,op2:2});Calculator.calc({type: "multiply",opl:5,op2:2));Calculator.calc({type: "divide",opl:8,op2:4));
职责链(Chain Of Responsibility)模式为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
组合(Composite)模式将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
享元(Flyweight)模式运用共享技术有效地支持大量细粒度的对象。
总结设计模式不是哪种编程语言特有的,它同样可以应用于Javascrip,各种设计模式建立在面��对象编程的基础上,而设计模式应用于前端也是在最近几年,只有通过连续不断的软件开发实践我们才能够灵活的运用设计模式。
参考资源http://www.www.digital-web.com/articles/excerpt_pro_javascript_patternshttp://aspalliance.com/1782_Working_with_GoFs_Design_Patterns_in_JavaScript_Programming.7http://michaux.ca/articles/the-command-pattern-in-javascript-encapsulating-function-property-callshttp://en.wikipedia.org/wiki/Strategy_pattern#JavaScripthttp://baike.baidu.com/view/66964.htmhttp://www.slideshare.net/rmsguhan/javascript-design-patterns
谢谢!

More Related Content

小谈Javascript设计模式