以下代码在ie6&ie6+&chrome测试通过,code地址:
https://code.csdn.net/liuyanzhi08/javascript_design_pattern/tree/master
1.单例模式(Singleton):
<html><head><title>Singleten-单例模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在singleten模块 MyNamespace.singleten = (function(){ var appid = 'helloJs'; return { getAppId:function(){ return appid; } }; })(); console.log(MyNamespace.singleten.getAppId()); </script> </body> </html>
<html><head><title>Factory-工厂模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在xhr模块 ,xhr其实就是一个工厂,生产函数是getXHR MyNamespace.xhr = (function(){ return { getXHR:function(){ methods = [ function(){ return new XMLHttpRequest(); }, function(){ return new ActiveXObject('Microsoft.XMLHTTP'); }, function(){ return new ActiveXObject('Msxml2.XMLHTTP'); } ] for(var i = 0; i < methods.length; i++){ try{ methods[i](); }catch(e){ continue; } this.getXHR = methods[i](); return methods[i](); } } } })(); alert(MyNamespace.xhr.getXHR()); </script> </body> </html>
3.桥接模式(Bridge)
<html><head><title>Bridge-桥接模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在request模块 MyNamespace.request = (function(){ function getXHR(){ methods = [ function(){ return new XMLHttpRequest(); }, function(){ return new ActiveXObject('Microsoft.XMLHTTP'); }, function(){ return new ActiveXObject('Msxml2.XMLHTTP'); } ] for(var i = 0; i < methods.length; i++){ try{ methods[i](); }catch(e){ continue; } this.getXHR = methods[i](); return methods[i](); } } function handleReadystate(xhr, callback){ xhr.onreadystatechange = function(){ if(xhr.readyState == 4 && xhr.status == 200){ if(callback){ callback(xhr.responseText); } } } } return function(method, uri, postData, callback){ //此处运用了桥接模式 var xhr = getXHR(); xhr.open(method, uri, true); handleReadystate(xhr, callback); xhr.send(postData || null); } })(); MyNamespace.request('post', 'test.php', "name=test&pwd=test", function(data){ alert(data); }) </script> </body> </html>
4.组合模式(Composite)
<html><head><title>Composite-组合模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在form模块 MyNamespace.form = (function(){ function Form(id, method, action){ this.element = document.createElement('form'); this.element.id = id; this.element.method = method; this.element.action = action; this.store = []; } Form.prototype = { add: function(fieldset){ this.element.appendChild(fieldset.getDom()); this.store.push(fieldset); }, getDom: function(){ return this.element; } } function Field(id){ this.element = document.createElement('fieldset'); this.element.id = id; this.store = []; } Field.prototype = { add: function(input){ this.element.appendChild(input.getDom()); this.store.push(input); }, getDom: function(){ return this.element; } } function Input(id, type, label){ this.wrapper = document.createElement('div'); var labelTextNode = document.createTextNode(label); this.label = document.createElement('label'); this.label.appendChild(labelTextNode); this.wrapper.appendChild(this.label); this.element = document.createElement(type); this.element.id = id; this.wrapper.appendChild(this.element); } Input.prototype = { getDom: function(){ return this.wrapper; } } return{ Form:Form, Field:Field, Input:Input } })(); window.onload = function(){ var form = new MyNamespace.form.Form('myForm', 'post', 'test.php'); var fields = [ new MyNamespace.form.Field('field1'), new MyNamespace.form.Field('field2'), new MyNamespace.form.Field('field3') ]; var inputs = [ [ new MyNamespace.form.Input('input1', 'input', 'input1:'), new MyNamespace.form.Input('input2', 'textarea', 'input2:'), new MyNamespace.form.Input('input3', 'input', 'input3:') ], [ new MyNamespace.form.Input('input4', 'textarea', 'input4:'), new MyNamespace.form.Input('input5', 'input', 'input5:'), new MyNamespace.form.Input('input6', 'input', 'input6:') ], [ new MyNamespace.form.Input('input7', 'input', 'input7:'), new MyNamespace.form.Input('input8', 'input', 'input8:'), new MyNamespace.form.Input('input9', 'textarea', 'input9:') ] ] for(var i = 0; i < fields.length; i++){ form.add(fields[i]); for(var j = 0; j < inputs.length; j++){ fields[i].add(inputs[i][j]); } } document.getElementsByTagName('body')[0].appendChild(form.getDom()); } </script> </body> </html>
5.门面模式(Facade)
<html><head><title>Facade-门面模式</title><meta charset="utf-8"></head> <body> <p id="greeting">Hello js!</p> <p id="greeting1">Hello js1!</p> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在even模块 MyNamespace.event = (function(){ return { setStyle: function(ids, prop, value){ for(var i = 0; i < ids.length; i++){ document.getElementById(ids[i]).style[prop] = value; } }, setCss: function(ids, styles){ for(var prop in styles){ if(!styles.hasOwnProperty(prop)){ continue; }else{ this.setStyle(ids, prop, styles[prop]); } } } } })(); MyNamespace.event.setCss(['greeting', 'greeting1'], { 'color': 'red', 'background': 'green' }) </script> </body> </html>
<html><head><title>Adapter-适配器模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在sample模块 MyNamespace.sample = (function(){ return { aFunctin: function(arg1, arg2, arg3){ alert(arg1); alert(arg2); alert(arg3); }, adapter: function(obj){ var i = 0; var args = []; for(var prop in obj){ if(!obj.hasOwnProperty(prop)) continue; args[i++] = obj[prop]; } this.aFunctin(args[0], args[1], args[2]); } } })(); // MyNamespace.sample.aFunctin('a', 'b', 'c'); MyNamespace.sample.adapter({ 'arg1':'a', 'arg2':'b', 'arg3':'c' }) </script> </body> </html>
7.装饰者模式(Decorator)
<html><head><title>Decorator-装饰者模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在sample模块 MyNamespace.sample = (function(){ function buildDom(){} buildDom.prototype = { startBuilt: function(){ var body = document.getElementsByTagName('body')[0]; for(var i = 0; i < 100; i++){ var list = document.createElement('ul'); for(var j = 0; j < 100; j++){ var item = document.createElement('li'); var text = document.createTextNode('test'); item.appendChild(text); list.appendChild(item); } body.appendChild(list); } } } function timeDetector(buildDom){ this.buildDom = buildDom; this.startTime; } timeDetector.prototype = { startRun: function(){ this.startTime = (new Date()).getTime(); }, stopRun: function(){ var runTime = (new Date()).getTime() - this.startTime; console.log("running cost:" + runTime + 'ms'); }, startBuilt: function(){ this.startRun(); this.buildDom.startBuilt(); this.stopRun(); } } return { buildDom: buildDom, timeDetector: timeDetector } })() window.onload = function(){ var buildDom = new MyNamespace.sample.buildDom(); var buildDom = new MyNamespace.sample.timeDetector(buildDom); buildDom.startBuilt(); } </script> </body> </html>
8.享元模式(Flyweight)
<html><head><title>Flyweight-享元模式</title><meta charset="utf-8"></head> <body> <style type="text/css"> .month{width: 200px;height:150px;padding:10px;border: 1px solid green; float: left;margin-right: 5px;margin-bottom: 5px;} .day{width: 15px;border: 1px solid green;float: left;margin-right: 5px;margin-bottom: 5px;padding: 2px;text-align: center;} </style> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在calendar模块 MyNamespace.calendar = (function(){ function Day(){} Day.prototype = { getDom: function(num){ var element = document.createElement('div'); element.className = 'day'; var text = document.createTextNode(num); element.appendChild(text); return element; } } var flyWeightDay = new Day(); function Year(year, parent) { this.element; this.parent = parent; this.isLeapYear = !(year%400) || (!(year%4) && (year%100)); this.months = []; for(var i = 0; i < 12; i++){ this.months.push(new Month(i, this.isLeapYear)); } this.buildDom(); } Year.prototype = { buildDom: function(parent){ this.element = document.createElement('div'); this.element.className = 'year'; for(var i = 0; i < this.months.length; i++){ var month = this.months[i]; month.buildDom(); this.element.appendChild(month.getDom()); } this.parent.appendChild(this.element); } } function Month(month, isLeapYear){ this.days = []; this.element; this.numDay; switch(month){ case 0: this.numDay = 31; break; case 1: this.numDay = isLeapYear?29:28; break; case 2: this.numDay = 31; break; case 3: this.numDay = 30; break; case 4: this.numDay = 31; break; case 5: this.numDay = 30; break; case 6: this.numDay = 31; break; case 7: this.numDay = 31; break; case 8: this.numDay = 30; break; case 9: this.numDay = 31; break; case 10: numDay = 30; break; case 11: this.numDay = 31; break; } } Month.prototype = { buildDom: function(){ this.element = document.createElement('div'); this.element.className = 'month'; for(var i = 0; i < this.numDay; i++){ this.element.appendChild(flyWeightDay.getDom(i+1)); } }, getDom: function(){ return this.element; } } return { Year:Year } })(); window.onload = function(){ var body = document.getElementsByTagName('body')[0]; new MyNamespace.calendar.Year(2004, body); } /****************************************************** * 非享元版:使用了几百个Day对象,占用内存很大 ***************************************/ // var MyNamespace = window.MyNamespace || {}; // // 定义在calendar模块 // MyNamespace.calendar = (function(){ // function Year(year, parent) { // this.element; // this.parent = parent; // this.isLeapYear = !(year%400) || (!(year%4) && (year%100)); // this.months = []; // for(var i = 0; i < 12; i++){ // this.months.push(new Month(i, this.isLeapYear)); // } // this.buildDom(); // } // Year.prototype = { // buildDom: function(parent){ // this.element = document.createElement('div'); // this.element.className = 'year'; // for(var i = 0; i < this.months.length; i++){ // var month = this.months[i]; // month.buildDom(); // this.element.appendChild(month.getDom()); // } // this.parent.appendChild(this.element); // } // } // function Month(month, isLeapYear){ // this.days = []; // this.element; // var numDay; // switch(month){ // case 0: // numDay = 31; // break; // case 1: // numDay = isLeapYear?29:28; // break; // case 2: // numDay = 31; // break; // case 3: // numDay = 30; // break; // case 4: // numDay = 31; // break; // case 5: // numDay = 30; // break; // case 6: // numDay = 31; // break; // case 7: // numDay = 31; // break; // case 8: // numDay = 30; // break; // case 9: // numDay = 31; // break; // case 10: // numDay = 30; // break; // case 11: // numDay = 31; // break; // } // for(var i = 1; i <= numDay; i++){ // this.days.push(new Day(i)); // } // } // Month.prototype = { // buildDom: function(){ // this.element = document.createElement('div'); // this.element.className = 'month'; // for(var i = 0; i < this.days.length; i++){ // var day = this.days[i]; // day.buildDom(); // this.element.appendChild(day.getDom()); // } // }, // getDom: function(){ // return this.element; // } // } // function Day(num){ // this.num = num; // this.element; // } // Day.prototype = { // buildDom: function(){ // this.element = document.createElement('div'); // this.element.className = 'day'; // var text = document.createTextNode(this.num); // this.element.appendChild(text); // }, // getDom: function(){ // return this.element; // } // } // return { // Year:Year // } // })(); // window.onload = function(){ // var body = document.getElementsByTagName('body')[0]; // new MyNamespace.calendar.Year(2004, body); // } </script> </body> </html>
9.代理模式(Proxy)
<html><head><title>Proxy-代理模式</title><meta charset="utf-8"></head> <body> <style type="text/css"> body{padding: :0;margin:0;overflow: hidden;font-family: "微软雅黑"} #modal-dialog{border: 3px solid green;padding: 10px;} #modal-close{position: absolute;top: -20px;right: -18px;cursor: pointer;border: 2px solid green;padding: 1px;border-radius:50% 50%;width: 15px;height: 15px;text-align: center;line-height: 12px;color: green;font-weight: bold;} #modal-loading{text-align: center;} </style> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在component模块 MyNamespace.component = (function(){ function Modal(option){ } Modal.prototype = { _addListener: function(){ var that = this; window.onresize = function(){ that._resizeMask(); that._repositionDialog(); } this.closeBtn.onclick = function(){ that.mask.parentNode.removeChild(that.mask); that.dialog.parentNode.removeChild(that.dialog); } }, _resizeMask: function(){ this.mask.style.width = '100%'; this.mask.style.height = document.body.clientHeight; }, _repositionDialog: function(){ this.dialog.style.left = (document.body.clientWidth-this.dialog.offsetWidth)/2; this.dialog.style.top = (document.body.clientHeight-this.dialog.offsetHeight)/3; }, show: function(){ var body = document.getElementsByTagName('body')[0]; //mask this.mask = document.createElement('div'); this.mask.id = 'modal-mask'; this.mask.style.position = 'absolute'; this.mask.style.left = 0; this.mask.style.top = 0; this.mask.style.background = '#000'; this.mask.style.opacity = '0.5'; this.mask.style.filter = 'alpha(opacity=50)'; this._resizeMask(); body.appendChild(this.mask); //diaglog this.dialog = document.createElement('div'); this.dialog.innerHTML = 'HELLO MODAL!'; this.dialog.id = 'modal-dialog'; this.dialog.style.position = 'absolute'; //close-button this.closeBtn = document.createElement('div'); var closeText = document.createTextNode('x'); this.closeBtn.id = 'modal-close'; this.closeBtn.appendChild(closeText); this.dialog.appendChild(this.closeBtn); body.appendChild(this.dialog); this._repositionDialog(); this._addListener(); } } function ModalProxy(){ this.interval = null; this.modal = new Modal(); this._initialize(); } ModalProxy.prototype = { _removeLoading: function(){ this.mask.parentNode.removeChild(this.mask); this.loading.parentNode.removeChild(this.loading); }, _resizeMask: function(){ this.mask.style.width = '100%'; this.mask.style.height = document.body.clientHeight; }, _repositionLoading: function(){ this.loading.style.left = (document.body.clientWidth-this.loading.offsetWidth)/2; this.loading.style.top = (document.body.clientHeight-this.loading.offsetHeight)/3; }, _initialize: function(){ var that = this; var body = document.getElementsByTagName('body')[0]; //mask this.mask = document.createElement('div'); this.mask.id = 'modal-loading-mask'; this.mask.style.position = 'absolute'; this.mask.style.left = 0; this.mask.style.top = 0; this.mask.style.background = '#000'; this.mask.style.opacity = '0.5'; this.mask.style.filter = 'alpha(opacity=50)'; this._resizeMask(); this.num = 0; body.appendChild(this.mask); //loading text this.loading = document.createElement('div'); this.loading.innerHTML = 'loading...'; this.loading.id = 'modal-loading'; this.loading.style.position = 'absolute'; body.appendChild(this.loading); this._repositionLoading(); window.onresize = function(){ that._resizeMask(); that._repositionLoading(); } this.interval = setTimeout(function(){ that._checkInitailization(); }, 100); }, _checkInitailization: function(callback){ var that = this; this.num++; //这里用num++ 来模拟等待数据处理的过程. this.num > 20为loading停止条件 if(this.num > 20){ clearTimeout(this.interval); this._removeLoading(); callback(); }else{ document.title = this.num; this.interval = setTimeout(function(){ that._checkInitailization(callback) }, 100); } }, show: function(){ var that = this; this._checkInitailization(function(){ that.modal.show(); }); } } return { ModalProxy:ModalProxy } })(); window.onload = function(){ var mp = new MyNamespace.component.ModalProxy(); mp.show(); } </script> 1. Singleton - 单例模式<br/> 2. Factory - 工厂模式<br/> 3. Bridge - 桥接模式<br/> 4. Composite - 组合模式<br/> 5. Facade - 门面模式<br/> 6. Adapter - 适配器模式<br/> 7. Decorator - 装饰者模式<br/> 8. Flyweight - 享元模式<br/> 9. Proxy - 代理模式<br/> </body> </html>
10.观察者模式(Observer)
<html><head><title>Observer-观察者模式</title><meta charset="utf-8"></head> <body> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在sample模块 MyNamespace.sample = (function(){ function Publisher(){ this.subscribers = []; } Publisher.prototype = { publish: function(msg){ for(var i in this.subscribers){ this.subscribers[i].msg = msg; } alert('Publish:"'+msg+'"'); } } function Subscriber(name){ this.name = name; this.msg; } Subscriber.prototype = { subscribe: function(publisher){ for(var i in publisher.subscribers){ if(publisher.subscribers[i] == this){ return; } } publisher.subscribers.push(this); }, getMsg: function(){ alert(this.name + ' has receive:"' + this.msg + '"'); } } return { Publisher:Publisher, Subscriber:Subscriber } })(); var p = new MyNamespace.sample.Publisher(); var s1 = new MyNamespace.sample.Subscriber('s1'); var s2 = new MyNamespace.sample.Subscriber('s2'); var s3 = new MyNamespace.sample.Subscriber('s3'); s1.subscribe(p); s2.subscribe(p); s3.subscribe(p); p.publish('new report'); s1.getMsg(); s2.getMsg(); s3.getMsg(); p.publish('another report') s1.getMsg(); s2.getMsg(); s3.getMsg(); </script> </body> </html>
11.命令模式(Command)
<html><head><title>Command-命令模式</title><meta charset="utf-8"></head> <body> <style type="text/css"> .memu{} .menu-item{padding: 5px 10px; background: green;width: 100px;cursor: pointer;margin-bottom: 1px;} </style> <script type="text/javascript"> var MyNamespace = window.MyNamespace || {}; // 定义在composite模块 MyNamespace.composite = (function(){ function Menu(parent){ this.parent = parent; this.element = document.createElement('div'); this.element.className = 'menu'; this.parent.appendChild(this.element); } Menu.prototype = { add: function(menuItem){ this.element.appendChild(menuItem.element); } } function MenuItem(name, command){ this.element = document.createElement('div'); this.element.className = 'menu-item'; var itemName = document.createTextNode(name) this.element.appendChild(itemName); this.command = command; this._addAction(); } MenuItem.prototype = { _addAction: function(){ var that = this; this.element.onclick = function(){ that.command.run(); } } } function Command(name){ this.name = name; } Command.prototype = { run: function(){ alert(this.name); } } return { Menu: Menu, MenuItem: MenuItem, Command: Command } })(); window.onload = function(){ var body = document.getElementsByTagName('body')[0]; var menu = new MyNamespace.composite.Menu(body); var editCommand = new MyNamespace.composite.Command('edit'); var saveCommand = new MyNamespace.composite.Command('save'); var menuItem = new MyNamespace.composite.MenuItem('选项一', editCommand); var menuItem1 = new MyNamespace.composite.MenuItem('选项二', saveCommand); menu.add(menuItem); menu.add(menuItem1); } </script> </body> </html>