摘要:書籍建造者類調(diào)用建造者高效能人士的七個(gè)習(xí)慣史蒂芬柯維勵(lì)志上面的這個(gè)類和第一個(gè)例子的效果一樣,但是長度確減少不少,在有更多屬性的時(shí)候,減少的代碼量會(huì)更為明顯。參考內(nèi)容設(shè)計(jì)模式張容銘
1 什么是建造者模式?
建造者模式(Builder)是將一個(gè)復(fù)雜對(duì)象的構(gòu)建層與其表示層相互分離,同樣的構(gòu)建過程可采用不同的表示。
建造者模式的特點(diǎn)是分步構(gòu)建一個(gè)復(fù)雜的對(duì)象,可以用不同組合或順序建造出不同意義的對(duì)象,通常使用者并不需要知道建造的細(xì)節(jié),通常使用鏈?zhǔn)秸{(diào)用來進(jìn)行建造過程,最后調(diào)用build方法來生成最終對(duì)象。
同樣作為創(chuàng)建型的設(shè)計(jì)模式,需要注意和工廠模式的區(qū)別,工廠雖然也是創(chuàng)建對(duì)象,但怎樣創(chuàng)建無所謂,工廠模式關(guān)注的是創(chuàng)建的結(jié)果;而建造者模式不僅得到了結(jié)果,同時(shí)也參與了創(chuàng)建的具體過程,適合用來創(chuàng)建一個(gè)復(fù)雜的復(fù)合對(duì)象。
2 ES6中的建造者模式下面我們來假設(shè)一個(gè)出版社的書籍后臺(tái)錄入系統(tǒng)的業(yè)務(wù)場景,書籍有四個(gè)必填信息,分別是:書名,作者,價(jià)格,分類;我們希望創(chuàng)建一個(gè)書籍對(duì)象返回給后端。下面我們來一步一步深入使用ES6的語法結(jié)合建造者模式創(chuàng)建對(duì)象。
//書籍建造者類 class BookBuilder { constructor() { this.name = ""; this.author = ""; this.price = 0; this.category = ""; } withName(name) { this.name = name; return this; } withAuthor(author) { this.author = author; return this; } withPrice(price) { this.price = price; return this; } withCategory(category) { this.category = category; return this; } build() { return { name: this.name, author: this.author, prices: this.price, category: this.category } } } //調(diào)用建造者類 const book = new BookBuilder() .withName("高效能人士的七個(gè)習(xí)慣") .withAuthor("史蒂芬·柯維") .withPrice(51) .withCategory("勵(lì)志") .build();
上面就通過我BookBuilder這個(gè)創(chuàng)建者類的寫法和調(diào)用方法,但是僅僅是一個(gè)4個(gè)屬性的對(duì)象,我們使用了如此多的代碼去創(chuàng)建,這遠(yuǎn)比直接在constructor傳遞參數(shù)創(chuàng)建對(duì)象要復(fù)雜得多。這是由于在創(chuàng)建的過程中,我們有太多的withxxxx方法。我們其實(shí)可以自動(dòng)創(chuàng)建這類withxxxx方法以簡化代碼。
//書籍建造者類 class BookBuilder { constructor() { this.name = ""; this.author = ""; this.price = 0; this.category = ""; Object.keys(this).forEach(key => { const withName = `with${key.substring(0, 1).toUpperCase()}${key.substring(1)}`; this[withName] = value => { this[key] = value; return this; } }) } //調(diào)用建造者 build() { const keysNoWithers = Object.keys(this).filter(key => typeof this[key] !== "function"); return keysNoWithers.reduce((returnValue, key) => { return { ...returnValue, [key]: this[key] } }, {}) } } const book = new BookBuilder() .withName("高效能人士的七個(gè)習(xí)慣") .withAuthor("史蒂芬·柯維") .withPrice(51) .withCategory("勵(lì)志") .build();
上面的BookBuilder這個(gè)類和第一個(gè)例子的效果一樣,但是長度確減少不少,在有更多屬性的時(shí)候,減少的代碼量會(huì)更為明顯。我們將所有的建造方法withxxxx在constructor調(diào)用時(shí)自動(dòng)被創(chuàng)建,這里我們使用了一些ES6的新語法:Object.keys獲取對(duì)象屬性數(shù)組,...的合并對(duì)象的語法。
雖然該寫法在閱讀起來會(huì)比第一個(gè)方法難以理解,但是這樣寫法的真正作用在于,當(dāng)我們需要許多的建造者類時(shí),我們可以將上面自動(dòng)創(chuàng)建withxxx和build的代碼提取為一個(gè)父類。在創(chuàng)建其他建造者類時(shí)繼承該父類,這使得在創(chuàng)建多個(gè)建造者類時(shí)變得十分容易。
//父類 class BaseBuilder { init() { Object.keys(this).forEach(key => { const withName = `with${key.substring(0, 1).toUpperCase()}${key.substring(1)}`; this[withName] = value => { this[key] = value; return this; } }) } build() { const keysNoWithers = Object.keys(this).filter(key => typeof this[key] !== "function"); return keysNoWithers.reduce((returnValue, key) => { return { ...returnValue, [key]: this[key] } }, {}) } } //子類1: 書籍建造者類 class BookBuilder extends BaseBuilder { constructor() { super(); this.name = ""; this.author = ""; this.price = 0; this.category = ""; super.init(); } } //子類2: 印刷廠建造者類 class printHouseBuilder extends BaseBuilder { constructor() { super(); this.name = ""; this.location = ""; this.quality = ""; super.init(); } } //調(diào)用書籍建造者類 const book = new BookBuilder() .withName("高效能人士的七個(gè)習(xí)慣") .withAuthor("史蒂芬·柯維") .withPrice(51) .withCategory("勵(lì)志") .build(); //調(diào)用印刷廠建造類 const printHouse = new printHouseBuilder() .withName("新華印刷廠") .withLocation("北京海淀區(qū)") .withQuality("A") .build();總結(jié)
在之前提到的幾種工廠模式中,他們都有一個(gè)共同特點(diǎn),就是對(duì)象的創(chuàng)建過程不得而知,我們?cè)谡{(diào)用一個(gè)函數(shù)后返回了最終的結(jié)果對(duì)象。但是在創(chuàng)建者模式中我們關(guān)心的是對(duì)象的創(chuàng)建過程,我們通常將創(chuàng)建復(fù)雜對(duì)象的各個(gè)類模塊化,在ES6中,我們采用import和export的語法可以很靈活的引用和導(dǎo)出這些模塊進(jìn)行我們的建造模式最終生成一個(gè)結(jié)果對(duì)象。
可以看出,建造者模式的使用有且只適合創(chuàng)建極為復(fù)雜的對(duì)象。在前端的實(shí)際業(yè)務(wù)中,在沒有這類極為復(fù)雜的對(duì)象的創(chuàng)建時(shí),還是應(yīng)該直接使用對(duì)象字面或工廠模式等方式創(chuàng)建對(duì)象。
參考內(nèi)容:
[1] An Exploration of JavaScript Builders —— Ryan Oglesby
[2] 《 JavaScript設(shè)計(jì)模式 》—— 張容銘
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/113424.html
摘要:書籍建造者類調(diào)用建造者高效能人士的七個(gè)習(xí)慣史蒂芬柯維勵(lì)志上面的這個(gè)類和第一個(gè)例子的效果一樣,但是長度確減少不少,在有更多屬性的時(shí)候,減少的代碼量會(huì)更為明顯。參考內(nèi)容設(shè)計(jì)模式張容銘 showImg(https://segmentfault.com/img/remote/1460000015147692); 1 什么是建造者模式? 建造者模式(Builder)是將一個(gè)復(fù)雜對(duì)象的構(gòu)建層與其表...
摘要:優(yōu)點(diǎn)建造者模式的封裝性很好,對(duì)象本身與構(gòu)建過程解耦。建造者模式很容易進(jìn)行擴(kuò)展。適用場景需要生成的對(duì)象具有復(fù)雜得內(nèi)部結(jié)構(gòu)且內(nèi)部屬性本身相互依賴建造者模式的代碼實(shí)現(xiàn)建造者模式主要有個(gè)部分產(chǎn)品類建造者類指揮者類客戶。建造者完成相應(yīng)的部分。 建造者模式 建造者模式(builder pattern)比較簡單,它屬于創(chuàng)建型模式的一種,將一個(gè)復(fù)雜的對(duì)象分解成多個(gè)簡單的對(duì)象來進(jìn)行構(gòu)建,將復(fù)雜的構(gòu)建層與...
摘要:注意事項(xiàng)聲明函數(shù)時(shí)候處理業(yè)務(wù)邏輯區(qū)分和單例的區(qū)別,配合單例實(shí)現(xiàn)初始化構(gòu)造函數(shù)大寫字母開頭推薦注意的成本。簡單工廠模式使用一個(gè)類通常為單體來生成實(shí)例。 @(書籍閱讀)[JavaScript, 設(shè)計(jì)模式] 常見設(shè)計(jì)模式 一直對(duì)設(shè)計(jì)模式不太懂,花了一下午加一晚上的時(shí)間,好好的看了看各種設(shè)計(jì)模式,并總結(jié)了一下。 設(shè)計(jì)模式簡介 設(shè)計(jì)模式概念解讀 設(shè)計(jì)模式的發(fā)展與在JavaScript中的應(yīng)用 ...
摘要:什么是裝飾器模式向一個(gè)現(xiàn)有的對(duì)象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)的設(shè)計(jì)模式被稱為裝飾器模式,它是作為現(xiàn)有的類的一個(gè)包裝。中的裝飾器模式中有一個(gè)的提案,使用一個(gè)以開頭的函數(shù)對(duì)中的及其屬性方法進(jìn)行修飾。 1 什么是裝飾器模式 showImg(https://segmentfault.com/img/remote/1460000015970102?w=1127&h=563); 向一個(gè)現(xiàn)有的對(duì)...
閱讀 3710·2021-11-19 09:40
閱讀 3164·2019-08-30 15:54
閱讀 2365·2019-08-30 15:44
閱讀 3253·2019-08-29 15:35
閱讀 3389·2019-08-29 12:22
閱讀 2914·2019-08-28 18:01
閱讀 3205·2019-08-26 13:54
閱讀 968·2019-08-26 12:24