javascript设计模式

Posted claireyuancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript设计模式相关的知识,希望对你有一定的参考价值。

  1. 单例模式(Singleton)
  2. 工厂模式(Factory)
  3. 桥接模式(Bridge)
  4. 组合模式(Composite)
  5. 门面模式(Facade)
  6. 适配器模式(Adapter)
  7. 装饰者模式(Decorator)
  8. 享元模式(Flyweight)
  9. 代理模式(Proxy)
  10. 观察者模式(Observer)
  11. 命令模式(Command)
下面代码在ie6&ie6+&chrome測试通过,code地址:
转载请注明出处:

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>

2.工厂模式(Factory)
<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>

6.适配器模式(Adapter)
<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>
































以上是关于javascript设计模式的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段12——JavaScript的Promise对象

VSCode自定义代码片段12——JavaScript的Promise对象

30秒就能看懂的JavaScript 代码片段

高效Web开发的10个jQuery代码片段

常用Javascript代码片段集锦

48个值得掌握的JavaScript代码片段(上)