javascript设计模式(javascript设计模式与开发实践读书笔记)

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点

// 单例模式简单实现
var Singleton = function( name ){
    this.name = name;
};
Singleton.prototype.getName = function(){ 
	alert ( this.name );
};
Singleton.getInstance = (function(){ 
	var instance = null;
	return function( name ){
		if ( !instance ){
			instance = new Singleton( name );
		}
		return instance; 
	}
})();
var a = Singleton.getInstance( 'sven1' ); 
var b = Singleton.getInstance( 'sven2' );
alert ( a === b ); // true

策略模式

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换

// 策略模式简单实现
var strategies = {
	"S": function( salary ){
		return salary * 4; 
	},
	"A": function( salary ){ 
		return salary * 3;
	},
	"B": function( salary ){
		return salary * 2;
	}
};
var calculateBonus = function( level, salary ){ 
	return strategies[ level ]( salary );
};
console.log( calculateBonus( 'S', 20000 ) ); 
console.log( calculateBonus( 'A', 10000 ) );

代理模式

为一个对象提供一个代用品或占位符,以便控制对它的访问

// 代理模式简单实现
var myImage = (function(){
	var imgNode = document.createElement( 'img' ); 
	document.body.appendChild( imgNode );
	return {
		setSrc: function( src ){
		imgNode.src = src; }
	} 
})();
var proxyImage = (function(){ 
	var img = new Image; 
	img.onload = function(){
		myImage.setSrc( this.src ); 
	}
	return {
		setSrc: function( src ){
			myImage.setSrc( 'file:// /C:/Users/svenzeng/Desktop/loading.gif' );
			img.src = src; 
		}
	} 
})();
proxyImage.setSrc( 'http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );

迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,从而不需要暴露该对象的内部表示。

// 迭代器模式简单实现
var iteratorUploadObj = function(){
	for ( var i = 0, fn; fn = arguments[ i++ ]; ){
		var uploadObj = fn();
		if ( uploadObj !== false ){
			return uploadObj;
		 } 
 	}
}
var uploadObj = iteratorUploadObj( getActiveUploadObj, getFlashUploadObj, getFormUpladObj );

发布-订阅模式

又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状 态发生改变时,所有依赖于它的对象都将得到通知
在 JavaScript 开发中,我们一般用事件模型 来替代传统的发布—订阅模式。

// 发布-订阅模式简单实现
var Event = (function(){
var clientList = {}, 
	listen,
	trigger, 
	remove;
listen = function( key, fn ){ 
	if ( !clientList[ key ] ){
		clientList[ key ] = []; 
	}
	clientList[ key ].push( fn ); 
};
trigger = function(){
	var key = Array.prototype.shift.call( arguments ),
		fns = clientList[ key ];
	if ( !fns || fns.length === 0 ){
		return false; 
	}
	for( var i = 0, fn; fn = fns[ i++ ]; ){ 
		fn.apply( this, arguments);
	}
};
remove = function( key, fn ){ 
	var fns = clientList[ key ]; 
	if ( !fns ){
		return false; 
	}
  	if ( !fn ){
		fns && ( fns.length = 0 );
	}else{
		for ( var l = fns.length - 1; l >=0; l-- ){
			var _fn = fns[ l ]; if(_fn===fn){
			fns.splice( l, 1 ); }
		} 
	}
};
return {
	listen: listen,
    trigger: trigger,
	remove: remove 
	}
})();
Event.listen( 
	'squareMeter88', 
	function( price ){
		console.log( '价格= ' + price ); 
	}
)
Event.trigger( 'squareMeter88', 2000000 );

命令模式

将请求封装成一个对象,从而让用户使用不同的请求把客户端参数化,以及支持可撤销和恢复的功能。

var closeDoorCommand = { execute: function(){
	console.log( '关门' ); }
};
var openPcCommand = { execute: function(){
	console.log( '开电脑' ); }
};
var openQQCommand = { execute: function(){
	console.log( '登录 QQ' ); }
};
var MacroCommand = function(){ 
	return {
		commandsList: [],
		add: function( command ){
			this.commandsList.push( command ); 
		},
		execute: function(){
			for ( var i = 0, command; command = this.commandsList[ i++ ]; ){
				command.execute(); 
			}
		} 
	}
};
var macroCommand = MacroCommand();
macroCommand.add( closeDoorCommand );
macroCommand.add( openPcCommand );
macroCommand.add( openQQCommand );
macroCommand.execute();

组合模式

将对象组合成树形结构来表示“部分-整体”的层次结构。
组合模式使得客户能以一致的方式处理个别对象和组合对象。

var MacroCommand = function(){ 
	return {
		commandsList: [],
		add: function( command ){
			this.commandsList.push( command ); 
		},
		execute: function(){
			for ( var i = 0, command; command = this.commandsList[ i++ ]; ){
				command.execute(); 
			}
		} 
	}
};
var openAcCommand = { 
	execute: function(){
		console.log( '打开空调' ); 
	}
};

var openTvCommand = { 
	execute: function(){
		console.log( '打开电视' ); 
	}
};
var openSoundCommand = { 
	execute: function(){
    	console.log( '打开音响' ); 
    }
};
var macroCommand1 = MacroCommand(); 
macroCommand1.add( openTvCommand ); 
macroCommand1.add( openSoundCommand );

var closeDoorCommand = { 
	execute: function(){
		console.log( '关门' ); 
	}
};
var openPcCommand = { 
	execute: function(){
		console.log( '开电脑' ); 
	}
};
var openQQCommand = { 
	execute: function(){
		console.log( '登录 QQ' ); 
	}
};
var macroCommand2 = MacroCommand(); 
macroCommand2.add( closeDoorCommand ); 
macroCommand2.add( openPcCommand ); 
macroCommand2.add( openQQCommand );
var macroCommand = MacroCommand(); 
macroCommand.add( openAcCommand ); 
macroCommand.add( macroCommand1 ); 
macroCommand.add( macroCommand2 );
macroCommand.execute(); 

模板方法模式

一种只需使用继承就可以实现的非常简单的模式
由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。通常 在抽象父类中封装了子类的算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺 序。子类通过继承这个抽象类,也继承了整个算法结构,并且可以选择重写父类的方法

// 抽象父类
var Beverage = function(){};
Beverage.prototype.boilWater = function(){ 
	console.log( '把水煮沸' );
};
Beverage.prototype.brew = function(){}; 
Beverage.prototype.pourInCup = function(){}; 
Beverage.prototype.addCondiments = function(){};
Beverage.prototype.init = function(){ 
	this.boilWater();
	this.brew();
	this.pourInCup(); 
	this.addCondiments();
};
// 具体子类
var Coffee = function(){}; 
Coffee.prototype = new Beverage();
Coffee.prototype.brew = function(){ 
	console.log( '用沸水冲泡咖啡' );
};
Coffee.prototype.pourInCup = function(){
	console.log( '把咖啡倒进杯子' );
 };
Coffee.prototype.addCondiments = function(){ 
	console.log( '加糖和牛奶' );
};
var Coffee = new Coffee(); 
Coffee.init();

享元模式

一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级。
享元模式的核心是运用共享技术来有效支持大量细粒度的对象

var Model = function( sex ){ 
	this.sex = sex;
};
Model.prototype.takePhoto = function(){
	console.log( 'sex= ' + this.sex + ' underwear=' + this.underwear);
};

var maleModel = new Model( 'male' ), 
femaleModel = new Model( 'female' );

for ( var i = 1; i <= 50; i++ ){ 
	maleModel.underwear = 'underwear' + i; 
	maleModel.takePhoto();
};

for ( var j = 1; j <= 50; j++ ){ 
	femaleModel.underwear = 'underwear' + j; 
	femaleModel.takePhoto();
};

职责链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间 5 的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

var order500 = function( orderType, pay, stock ){ 
	if ( orderType === 1 && pay === true ){
		console.log( '500 元定金预购, 得到 100 优惠券' ); 
	}else{
		order200( orderType, pay, stock ); // 将请求传递给 200 元订单 
	}
};
// 200 元订单
var order200 = function( orderType, pay, stock ){ 
	if ( orderType === 2 && pay === true ){
		console.log( '200 元定金预购, 得到 50 优惠券' ); 
	}else{
		orderNormal( orderType, pay, stock ); // 将请求传递给普通订单 
	}
};
// 普通购买订单
var orderNormal = function( orderType, pay, stock ){ 
	if ( stock > 0 ){
		console.log( '普通购买, 无优惠券' ); 
	}else{
		console.log( '手机库存不足' ); 
	}
};
// 测试结果:
order500( 1 , true, 500); // 输出:500 元定金预购, 得到 100 优惠券 
order500( 1, false, 500 ); // 输出:普通购买, 无优惠券
order500( 2, true, 500 ); // 输出:200 元定金预购, 得到 500 优惠券 
order500( 3, false, 500 ); // 输出:普通购买, 无优惠券
order500( 3, false, 0 ); // 输出:手机库存不足

中介者模式

中介者模式是迎合迪米特法则的一种实现。
迪米特法则也叫最少知识原则,是指一个对象应 该尽可能少地了解另外的对象(类似不和陌生人说话)。
中介者模式使各个对象之间得以解耦,以中介者和对象之间的一对多关系取代了对象 之间的网状多对多关系。各个对象只需关注自身功能的实现,对象之间的交互关系交给了中介者 对象来实现和维护。

var goods = { // 手机库存 
	"red|32G": 3, 
	"red|16G": 0, 
	"blue|32G": 1, 
	"blue|16G": 6
}
var mediator = (function(){
	var colorSelect = document.getElementById( 'colorSelect' ), 
	memorySelect = document.getElementById( 'memorySelect' ), 
	numberInput = document.getElementById( 'numberInput' ), 
	colorInfo = document.getElementById( 'colorInfo' ), 
	memoryInfo = document.getElementById( 'memoryInfo' ), 
	numberInfo = document.getElementById( 'numberInfo' ), 
	nextBtn = document.getElementById( 'nextBtn' );
	return {
		changed: function( obj ){
			var color = colorSelect.value, // 颜色 
			memory = memorySelect.value,// 内存 
			number = numberInput.value, // 数量 
			stock = goods[ color + '|' + memory ];
			// 颜色和内存对应的手机库存数量
			if ( obj === colorSelect ){ // 如果改变的是选择颜色下拉框 
				colorInfo.innerHTML = color;
			}else if ( obj === memorySelect ){ 
				memoryInfo.innerHTML = memory;
			}else if ( obj === numberInput ){ 
				numberInfo.innerHTML = number;
			}
			if ( !color ){
				nextBtn.disabled = true; 
				nextBtn.innerHTML = '请选择手机颜色'; 
				return;
			}
			if ( !memory ){
				nextBtn.disabled = true; 
				nextBtn.innerHTML = '请选择内存大小'; 
				return;
			}
			if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ 
				nextBtn.disabled = true;
				nextBtn.innerHTML = '请输入正确的购买数量'; 
				return;
			}
			nextBtn.disabled = false;
			nextBtn.innerHTML = '放入购物车'; 
		}
	}
})();
// 事件函数:
colorSelect.onchange = function(){
	mediator.changed( this ); 
};
memorySelect.onchange = function(){ 
	mediator.changed( this );
};
numberInput.oninput = function(){
	mediator.changed( this ); 
};

装饰者模式

给对象动态地增加职责的方式
装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。跟继承相比,装饰者是一种更轻便灵活的做法

var plane = {
	fire: function(){
		console.log( '发射普通子弹' ); 
	}
}
var missileDecorator = function(){ 
	console.log( '发射导弹' );
}
var atomDecorator = function(){ 
	console.log( '发射原子弹' );
}
var fire1 = plane.fire;
plane.fire = function(){ 
	fire1();
	missileDecorator(); 
}
var fire2 = plane.fire;
plane.fire = function(){ 
	fire2();
	atomDecorator(); 
}
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹

状态模式

允许一个对象在其内部状态改变时改变它的行为

var Light = function(){
	this.currState = FSM.off; // 设置当前状态 this.button = null;
};
Light.prototype.init = function(){
	var button = document.createElement( 'button' ),
	self = this;
	button.innerHTML = '已关灯';
	this.button = document.body.appendChild( button );
	this.button.onclick = function(){ 
		self.currState.buttonWasPressed.call( self );
	} 
};
var FSM = { 
	off: {
		buttonWasPressed: function(){
			console.log( '关灯' ); 
			this.button.innerHTML = '下一次按我是开灯'; 
			this.currState = FSM.on;
		} 
	},
	on: {
		buttonWasPressed: function(){
			console.log( '开灯' ); 
			this.button.innerHTML = '下一次按我是关灯'; 
			this.currState = FSM.off;
		}
	}
}
var light = new Light(); 
light.init();

适配器模式

解决两个软件实体间的接口不兼容的问题

var getGuangdongCity = function(){ 
	var guangdongCity = [
		{
			name: 'shenzhen', 
			id: 11,
		}, 
		{
			name: 'guangzhou', 
			id: 12,
		}
	]
	return guangdongCity;
}
var render = function( fn ){
	console.log( '开始渲染广东省地图' ); 
	document.write( JSON.stringify( fn() ) );
};
var addressAdapter = function( oldAddressfn ){
	var address = {},
	oldAddress = oldAddressfn();
	for ( var i = 0, c; c = oldAddress[ i++ ]; ){ 
		address[ c.name ] = c.id;
	}
	return function(){ 
		return address
	} 
};
render( addressAdapter( getGuangdongCity ) );

单一职责原则

就一个类而言,应该仅有一个引起它变化的原因

最少知识原则

一个软件实体应当尽可能少地与其他实体发生相互作用

开放-封闭原则

软件实体(类、模块、函数)等应该是可以扩展的,但是不可修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值