目录
工厂模式
方便经常创建某个对象,我们可以把这个对象封装成一个可以调用的函数,可以随时通过调用该函数获得自己需要的对象。
function factory(type) { switch (type) { case "type1": return { name: "类型1" }; break; case "type2": return { name: "类型2" }; break; case "type3": return { name: "类型3" }; break; default: break; } } const obj = factory("type1");//{ name: "类型1" }
建造者模式
当需要创造一个单一庞大的对象时,把对象各个部分拆成单独的类,然后根据需求组合在一起,由最终类提供需要的对象。
const head = { name: "头部", }; const foot = { name: "脚部", }; function final() { return { head, foot, }; } const obj = final();//{ head: { name: "头部" }, foot: { name: "脚部" } }
单例模式
某个对象,全局只允许存在一个的时候,即便被重复创建,获得的仍然是原来的对象。
function single(name) { return this.instant ? this.instant : (this.instant = { name }); } const obj1 = single("123");//{name:"123"} const obj2 = single("1");//{name:"123"}
桥接模式
把重复的方法抽样出来,每个方法都可以被高度复用,且抽样出来的单位可以独立与桥接函数进行修改,再桥接出去。
有点类似建造者模式?是这样的,但是他们的本质不同。
建造者模式核心是构造对象,而桥接模式是为了简化代码,提高复用性。
区别就是一个关注创建一个关注功能。
function way(wayName) { return { wayName, }; } function destination(destinationName) { return { destinationName, }; } //由桥接来实现对上述两种抽象方法的利用 function bridge(wayName, destinationName) { const wayObj = way(wayName); const destinationObj = destination(destinationName); console.log(wayObj.wayName + "去" + destinationObj.destinationName); } bridge("坐船", "北京");//坐船去北京
享元模式
为了减少对象数量,提取共有部分,私有部分从外部传入。
我们可以结合桥接模式的例子,如果我们交通方式不可变,我们只有一艘船,需要坐船去各个地方。
function way(wayName) { return { wayName, }; } function destination(destinationName) { return { destinationName, }; } function bridge(wayName, destinationName) { const wayObj = way(wayName); const destinationObj = destination(destinationName); console.log(wayObj.wayName + "去" + destinationObj.destinationName); } bridge("坐船", "北京"); //坐船去北京 bridge("坐船", "上海"); //坐船去上海 bridge("坐船", "湖南"); //坐船去湖南
你会发现这些例子中,在桥接函数中,坐船那个方式对象被重复创建了。
享元模式就是需要避免重复创建不必要的对象。
将共有部分坐船提取出来,而私有部分不同的目的地仍然从外部传入。
意味着我们坐的一直都是同一艘船。
function way(wayName) { return { wayName, }; } function destination(destinationName) { return { destinationName, }; } function bridge(wayObj, destinationName) { const destinationObj = destination(destinationName); console.log(wayObj.wayName + "去" + destinationObj.destinationName); } const wayObj = way("坐船"); bridge(wayObj, "北京"); //坐船去北京 bridge(wayObj, "上海"); //坐船去上海 bridge(wayObj, "湖南"); //坐船去湖南
模板方法模式
这个模式就是有一系列算法,但是有些部分可以在使用时定义,也就是给你模板,你自定义一些部分然后使用。
function counter() { return { beforeCounter: [], afterCounter: [], addBefore: function (fn) { this.beforeCounter.push(fn); }, addAfter: function (fn) { this.afterCounter.push(fn); }, count: function (num) { //结果变量 var resultnum = num; //算法队列数组组装 function baseCount(num) { num *= 2; return num; } var arr = [baseCount]; arr = this.beforeCounter.concat(arr); arr = arr.concat(this.afterCounter); //不同部分的相同算法骨架 //循环执行算法队列 while (arr.length > 0) { resultnum = arr.shift()(resultnum); console.log(resultnum) } return resultnum; } } } //使用 var countObject = counter(); countObject.addBefore(function (num) { num--; return num; }) countObject.addAfter(function (num) { num++; return num; }) countObject.count(10)
这是一个连续计算的计算器,中间维护了一个数组,数组内有自己添加的计算过程(函数),也有中间公共的计算过程。
适配器模式
将不适合我们使用的数据通过适配器转化成我们需要的数据。
const arr = ['月亮', '18', '男'] const adapter = (arr) => { return { name: arr[0], age: arr[1], sex: arr[2] } } console.log(adapter(arr))//{name: '月亮', age: '18', sex: '男'}
例子很简单,只是传达一种思想,实际中的适配器可能会更为复杂,但是目的是一致的。
装饰者模式
js使用装饰者模式没有其他语言那么困难,其实可以直接重写对象,不过这显然不太好,当别人封装了一个函数,你想要在旧的函数基础上装饰上新的内容。
const test = () => { console.log('旧内容') } const _test = test const newTest = () => { _test() console.log('新内容') } newTest()//旧内容 新内容
命令模式
将一些方法保存在内部,通过输入指令依次执行。
const design = (() => { const action = { triangle: (val) => { console.log('画一个边长为' + val + '的三角形') }, circle: (val) => { console.log('画一个周长为' + val + '的圆') } } return function excute(actions) { actions.forEach(act => { const { actName, actVal } = act action[actName](actVal) }); } })() design([ { actName: 'triangle', actVal: '3' }, { actName: 'circle', actVal: '3' } ]) //画一个边长为3的三角形 //画一个周长为3的圆
观察者模式
就是事件订阅和绑定,我们可以自己写一个绑定代码
const Event = { on: function (eventName, callback) { this.actions = this.actions ? this.actions : {} this.actions[eventName] = callback }, emit: function (eventName, val) { if (this.actions[eventName]) { this.actions[eventName](val) } } }; Event.on('test', function (result) { console.log(result); }); Event.emit('test', 'hello world'); // 'hello world'
这里代码没有考虑Event的拓展性和可复用性,只是为了让人简单了解观察者模式。
职责链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间 的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
function cat(type) { if (type == "cat") { console.log("我是猫猫"); } else { return "nextSuccessor" } } function dog(type) { if (type == "dog") { console.log("我是狗狗"); } else { return "nextSuccessor" } } function pig(type) { if (type == "pig") { console.log("我是猪猪"); } else { return "nextSuccessor" } } Function.prototype.after = function (fn) { var _self = this; return function () { var ret = _self.apply(this, arguments); if (ret === "nextSuccessor") { return fn.apply(this, arguments); } return ret } } var pet = cat.after(dog).after(pig); pet("pig"); //我是猪猪 pet("dog"); //我是狗狗 pet("cat"); //我是猫猫
这个例子可能after代码可能很难理解,但是主要传递的是解耦链式的思想。