JavaScript程序设计模式例子整理总结笔记

自从读了《代码整洁之道-程序员的职业素养》后,闲人照计划找了几本有关设计模式的书去学习。今天闲人来总结下学到的东西。
感觉国内的书,翻译得都不太好让人吸收,常出现一些没有注释且难以理解的词句,不过还是要谢谢译者们的辛苦,让我这种英语水平低下的人,也有机会吸收更多知识。


模式列表

设计原则

SOLID五大原则

SOLID 是由5个设计原则的英文首字母组成

单一责任原则

英文:Single Responsibility Principle
简写:SRP
说明一个类或模块只负责一个功能领域中的相应职责
补充:是实现高内聚低耦合的指导方针

开放/封闭原则

英文:Open/Closed Principle
简写:OCP
说明软件实体应对扩展开放,而对修改关闭
补充:为了满足开闭原则,必须对系统进行抽象设计

里氏代换原则

英文:Liskov Substitution Principle
简写:LSP
说明所有引用基类对象的地方能够透明地使用其子类的对象

接口隔离原则

英文:Interface Segregation Principle
简写:ISP
说明使用多个专门的接口,而不使用单一的总接口

依赖反转原则

英文:Dependency Inversion Principle
简写:DIP
说明抽象不应该依赖于细节,细节应该依赖于抽象
补充:对抽象层进行编程,而不对具体实现进行编程

其它设计原则

迪米特法则

英文:Law of Demeter
简写:LOD
说明一个软件实体应当尽可能少的与其他实体发生相互作用
补充: 别称最少知识原则

合成复用原则

英文:Composite Reuse Principle
简写:CRP
说明尽量使用对象组合,而不是继承来达到复用的目的

不要重复原则

英文:Dont’t Repeat Yourself
简写:DRY
说明同一个方法,在同一个系统中不要出现两次
补充: 该原则有一定局限性,主要用来提高代码质量。

常用设计模式24种

创建型模式5种

单例模式:一个类在全局访问点只有唯一一个实例

class World {
	constructor(){
		if(World.instance) return World.instance;
		World.instance = this;
	}
}

饿汉单例:系统加载即初始化
懒汉单例:对象在初次使用时进行初始化
多例模式:是单例模式的衍生,一般用于对象池

const idleInstance = [];
const busyInstance = [];
class Pool {
	constructor(){
		if(idleInstance.length){
		 	const instance = Pool.idleInstance.pop();
		 	busyInstance.push(instance);
		 	return instance;
		}
		if(busyInstance.length > 5) throw Error('无可用对象');
		busyInstance.push(this);
	}
	workEnd(){
		const index = busyInstance.indexOf(this);
		if(index !== -1){
		 	idleInstance.push(this);
			busyInstance.splice(index, 1);
		}
	}
}

原型模式:用于复制或克隆完全初始化的实例

const prototype = { a: 1 };
function C(){};
C.prototype = prototype;

工厂方法:基于接口数据或事件生成几个派生类的一个实例

const GoodsFactorys = {};
class GoodsFactory {};
function addGoodsFactory(type, builder){
	GoodsFactorys[type] = builder(GoodsFactory);
}
addGoodsFactory('Goods1', function(GoodsFactory){
	return class Goods1 extends GoodsFactory {}
});
addGoodsFactory('Goods2', function(Factory){
	return class Goods2 extends GoodsFactory {}
});
function getInstance(type, ...args){
	const Goods = GoodsFactorys[type] || GoodsFactory;
	return new Goods(...args);
}

简单工厂模式:只能生成一个类的实例方法
所有单独存在的类都可以被称为简单工厂模式

抽象工厂:创建若干类系列的一个实例,无需详述具体的类

const ShopFactorys = {};
function ShopFactory(callback){
	const GoodsFactorys = {};
	class GoodsFactory {};
	function addGoodsFactory(type, builder){
		GoodsFactorys[type] = builder(GoodsFactory);
	}
	addGoodsFactory('Goods1', function(GoodsFactory){
		return class Goods1 extends GoodsFactory {}
	});
	addGoodsFactory('Goods2', function(Factory){
		return class Goods2 extends GoodsFactory {}
	});
	return function getInstance(type, ...args){
		const Goods = GoodsFactorys[type] || GoodsFactory;
		return new Goods(...args);
	}
}
function addShopFactory(type, builder){
	ShopFactorys[type] = builder(ShopFactory);
}
addShopFactory('Shop1', function(ShopFactory){
	return ShopFactory(function(addGoodsFactory){
		addGoodsFactory('Goods3', function(GoodsFactory){
			return class Goods3 extends GoodsFactory {}
		});
		addGoodsFactory('Goods4', function(GoodsFactory){
			return class Goods4 extends GoodsFactory {}
		});
	});
});
addShopFactory('Shop2', function(ShopFactory){
	return ShopFactory(function(addGoodsFactory){
		addGoodsFactory('Goods5', function(GoodsFactory){
			return class Goods5 extends GoodsFactory {}
		});
		addGoodsFactory('Goods6', function(GoodsFactory){
			return class Goods6 extends GoodsFactory {}
		});
	});
});
function getFactory(type){
	return Factorys[type] || Factory;
}

抽象工厂也可以返回其它抽象工厂

生成器模式:从表示中分离对象构建,总是创建相同类型的对象

class Builder {
	constructor(options){
		this.buildStep1(options || {});
		this.buildStep2(options || {});
		this.buildStep3(options || {});
	}
	buildStep1(options){
		this.type = options.type;
	}
	buildStep2(options){
		this.name = options.name;
	}
	buildStep3(options){
		Object.assign(this, options);
	}
}

常把复杂对象的初始化方法拆分成多个步骤

结构型模式7种

适配器模式:匹配不同类的接口,因此类可以在不兼容接口的情况下共同工作

class Wrapper{
	constructor(instance){
		this.instance = instance; 
	}
	async method(...args){
		return Promise.resolve(this.instance.method(...args))
	}
}

桥接模式:将对象接口从其实现中分离,因此它们可以对立进行变化

class Methods {
	construtor(Bridge){
		this.Bridge = Bridge;
	}
	method(){
		console.log(this.Bridge.value)
	}
}

组合模式:简单和复合对象的结构,使对象的总和不只是它各部分的总和

const people = new People();
const monkey = new Monkey();
const monkeyPeople = {
	name: 'monkeyPeople',
	run: People.prototype.run,
	jump: Monkey.prototype.jump,
}

装饰器模式:向对象动态添加备选的处理

function Decorator(people){
	const see = people.see;
	people.see = function(target){
		see.call(people, target);
		if(target.name === 'sun'){
			people.dead();
		}
	}
	return people;
}
const people = Decorator(new People());

外观模式:隐藏整个子系统复杂性的唯一一个类

const people = new People();
function facade(){
	people.see('mirror');
	people.draw('eyebrow');
	return people.face();
}

享元模式:运用共享技术来有效支持大量细粒度的对象

var shareData = {};
function usedShareData1(){
	shareData.value = 1;
	shareData.created = 1;
}
function usedShareData2(){
	shareData.value = 2;
	shareData.updated = 1;
}

代理模式:占位符对象代表真正的对象

function targetAccpet(fromSign){
	if(fromSign === 0) throw Error('不接受该信息');
	console.log('成功接受代理信息');
}
function agentAccpet(fromSign){
	targetAccpet(1);
}
function sendToAgent(){
	agentAccpet(0);
	targetAccpet(0);
}

行为模式12种

解释器模式:将语言元素包含在应用程序中的方法,以匹配预期语言的语法

function PlusInterpreter(value){
	const [left,right] = value.split('+');
	if(isNaN(left) || isNaN(right)) throw Error('语法错误');
	return left * 1 + right * 1;
}

模版方法:在方法中创建算法的shell,然后将确切的步骤推到子类

function PlusTemplate(left, right){
	if(isNaN(left) || isNaN(right)) throw Error('语法错误');
	return PlusInterpreter(left + '+' + right);
}

职责链模式:在对象链之间传递请求的方法,以找到能够处理请求的对象

function method1(options){
	console.log('method1');
}
function methodAnother(options){
	console.log('methodAnother');
}
function method(options){
	switch(options.next){
		case 'method1':
			method1(options);
			break;
		default:
			methodAnother(options);
	}
}

命令模式:将命令执行从其调用程序中分离的方法

const Command = {
	Set(key, _, value){
		console.log('设置' + key + '为' + value);
	}
	execute(value){
		const [cmd,...args] = value.split(/s+/);
		if(!this[cmd]) throw Error('命令不存在');
		this[cmd](...args);
	}
}
Command.execute('Set ENV is local');

迭代器模式:顺序访问一个集合中的元素,无需了解该集合的内部工作原理

function map(obj,callback){
	return Object.keys(obj).map((k,i)=>callback(obj[k],k,i));
}

中介者模式:在类之间定义简化的通信,以防止一组类显式引用彼此

let events = [];
function on(callback){
	events.push(callback)
}
function emit(){
	const copy = events;
	events = [];
	copy.forEach(fn=>fn());
}

备忘录模式:捕获对象的内部状态,以能够在以后恢复它

const source = { a: 1 };
const remark = JSON.stringify(source);
source.a = 2;
Object.assign(source, JSON.parse(remark));

观察者模式:向多个类通知改变的方式,以确保类之间的一致性

const objects = [];
function on(e){
 	objects.push(e);
}
function emit(key){
	objects.forEach(e=>e[key]());
}

状态模式:状态改变时,更改对象的行为

let state = false;
function toggle(){
	state = !state;
}

策略模式:在一个类中封装算法,将选择与实现分离

function Strategy(options){
	switch(options.type){
		case 1:
			return options.a1;
		case 2:
			return options.a2 + options.a3;
		default:
			return options.a;
	}
}

访问者模式:向类添加一个新的操作,无需改变类

function entry(){
	console.log(this.value);
}
entry.call({ value: 1 });

空对象模式:向类添加一个新的操作,无需改变类

function Run(object){
	if(object !== null){
		console.log(object);
	}else{
		console.log({ value: 'emptyObject' })
	}
}

总结

闲人看了许多资料,各个资料对设计模式的理解都有出入,闲人认为,目前的设计模式,是针对面向对象语言的惯例,在针对JavaScript这种不是完全面向对象的语言来说,它并不是完全适用,有待后人整理出不同的,专用于JavaScript的设计模式来。闲人也会持续学习并更新所学的知识,希望对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲人老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值