1. 建造者模式
建造者模式:将一个复杂对象的构建和它的表示分离, 使得同样的构建和创建出不同的表示。当我们构建的对象内部结构非常复杂时,利用建造者模式将内部各模块分开创建就非常合适。
1.1 为什么要用建造者模式?
- 客户端不必知道产品内部组成的细节, 将产品本身和产品的创建过程解耦,使得相同的创建过程可以创建标题的重排对象。
- 每一个建造者都相对独立,而已其他的具体建造者无关,因此可以很方便的替换具体建造者或增加新的具体的建造者。
- 可以更加精细的控制重排的创建过程。将复杂重排的创建步骤分解在不同的方法中,使得创建过程更加精细,也更方便使用程序控制创建过程。
1.2 起步
建造者模式看名字我们首先想到的就是造房子。建造者模式就像是施工团队,包工头和客户沟通建房的具体建房需细节,然后在自己团队内部发布任务,将复杂的建房工程分成了若干小组,各小组分工合作最终得到需求的房子。
假设我们需要建设一套6人住,150平方m²,中式风格的房子,此时我们使用建造者模式就非常合适。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| let Builder = (function () { function rooms(peopleCount) { if(peopleCount <= 0) throw new Error("入住人数异常"); this.peopleCount = peopleCount < 3 ? 2 : peopleCount } function setArea(area){ if(area <= 20) throw Error("房子面积过小") this.area = area } function style(style){ this.style = style } return class{ constructor(PeopleCount,area,Style){ rooms.call(this, PeopleCount) setArea.call(this, area); style.call(this, Style) } } })() let bighouse = new Builder(3,100,'中式'), smallHouse = new Builder(3,50,'欧式');
|
关键点:
1 2 3 4 5 6 7 8 9
| let Builder = (function () { function rooms(){} function setArea(){} function style(){} return class { } })();
|
通过上面的例子我们也对建造者模式的概念用来一定的了解,Jquery内部就用到了建造者模式,jQuery的美元标记为动态构建新的jQuery(和DOM)对象提供了大量可以让我们这样做的不同的方法,可以通过给一个元素传入完整的标签,也可以是部分标签还有内容,或者使用jQuery来进行构造。
建造者模式使得我们仅仅只通过定义对象的类型和内容,就可以构建复杂的对象,为我们屏蔽了明确创造或展现对象的过程。
下面是一个简单的构建Dom元素的demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| let BuilddEle = ( function (params) { function createEle(eleName) { this.ele = document.createElement(eleName); } function setText(text) { this.ele.textContent = text; } function setStyle(style) { Object.entries(style).forEach(([key,val]) =>{ if (["width", "height","margin","padding"].includes(key)) { if(typeof val !== "string") throw new Error( key + '--prototype type Error'); if(!val.includes("px")){ console.warn(key + "应该添加px结尾"); this.ele.style[key] = val + "px"; } this.ele.style[key] = val; } else { this.ele.style[key] = val } }) } function setAttr(attrS){ Object.entries(attrS).forEach( ([key,val]) =>{ this.ele.setAttribute(key,val) }) } return class{ constructor(eleName,text,styleS,attrS){ createEle.call(this,eleName); setText.call(this,text); setStyle.call(this, styleS); setAttr.call(this,attrS) } render(target){ if(target instanceof Node){ target.appendChild(this.ele) }else if(typeof target === "string"){ let targelEle = document.querySelector(target); if(targelEle === null) throw new Error('the target element was not obtained'); targelEle && targelEle.appendChild(this.ele); }else{ document.body.append(this.ele) } } } })() let style = { width: 100, height: 100, color: "white", backgroundColor: "red" } let div = new BuilddEle('div',"ddd", style,{class:'age'}); div.render()
|
总结
: 当我们构造的对象,内部结构非常复杂时,使用建造者模式将内部模块分开创建就非常合适。