建造者模式——分即是合
建造者模式: 將一個(gè)復(fù)雜對(duì)象的構(gòu)建層與其表示層相互分離,同樣的構(gòu)造過程可采用不同的表示刁岸。
對(duì)比
工廠模式主要是為了創(chuàng)建對(duì)象實(shí)例或者類簇(抽象工廠),關(guān)心的是最終產(chǎn)出(創(chuàng)建)的是什么
工廠模式不關(guān)心創(chuàng)建的整個(gè)過程,僅僅需要知道最終的創(chuàng)建結(jié)果,通過工廠模式得到的都是對(duì)象實(shí)例或者類簇
建造者模式在創(chuàng)建對(duì)象時(shí)更為復(fù)雜佛猛,雖然目的也是為了創(chuàng)建對(duì)象,但是這個(gè)模式更多關(guān)心的是創(chuàng)建這個(gè)對(duì)象的整個(gè)過程(比如創(chuàng)建一個(gè)人坠狡,我們創(chuàng)建的結(jié)果不僅僅是要得到人的實(shí)例继找,還要關(guān)注創(chuàng)建人的時(shí)候,這個(gè)人應(yīng)該穿什么衣服逃沿,男的還是女的婴渡,興趣愛好都是什么), 所以建造者模式更注重的是創(chuàng)建的的細(xì)節(jié)。
比如在發(fā)布簡(jiǎn)歷的需求中凯亮,我們需要的不僅僅是應(yīng)聘者的一個(gè)實(shí)例边臼,還要在創(chuàng)建過程中注意一下這位應(yīng)聘者都有哪些興趣愛好、他的姓名等信息假消,他所期望的職位是什么柠并,等等,這些細(xì)節(jié)關(guān)注點(diǎn)都需要我們創(chuàng)建富拗。
首先臼予,需要的人類的類,和人類的姓名類啃沪、職位類等(在類里使用閉包粘拾,可以讓這個(gè)閉包既是閉包,又是這個(gè)類的構(gòu)造函數(shù))
// 創(chuàng)建一位人類
var Human = function(param){
// 技能
this.skill = param && param.skill || '保密'创千;
// 興趣愛好
this.hobby = param && param.hobby || '保密'
}
// 人類類的原型
Human.prototype = {
getSkill: function(){
return this.skill
},
getHobby: function(){
return this.hobby
}
}
// 實(shí)例化姓名類
var Named = function(name){
var that = this;
// 構(gòu)造器
// 構(gòu)造函數(shù)解析姓名的姓與名
(function(name, that){
that.wholeName = name // 緩存這個(gè)name
if(name.indexOf(' ')> -1){
that.firstName = that.wholeName.slice(0, that.wholeName.indexOf(' '));
that.secondName = that.wholeName.slice(that.wholeName.indexOf(' '))
}
})(name, that)
}
// 實(shí)例化職位類
var Work = function(work){
var that = this
// 構(gòu)造器
// 構(gòu)造函數(shù)中通過傳入的職位特征來設(shè)置相應(yīng)職位以及描述
(function(work,that){
switch(work){
case 'code':
that.work = '工程師';
that.workDescript = '每天沉醉于編程';
break;
case 'UI':
case 'UE':
that.work = '設(shè)計(jì)師';
that.workDescript = '設(shè)計(jì)更似一種藝術(shù)';
break;
case 'teach':
that.work = '教師';
that.workDescript = '分享也是一種快樂';
break;
default:
that.work = work;
that.workDescript = '對(duì)不起缰雇,我們還不清楚您所選擇職位的相關(guān)描述'入偷;
}
})(work, that)
}
// 更換期望的職位
Work.prototype.changeWork = function(work){
this.work = work
}
// 添加更換職位的描述
Work.prototype.changeDescript = function(setence){
this.workDescript = setence
}
我們就創(chuàng)建了抽象出來的三個(gè)類——應(yīng)聘者類、姓名解析類與期望職位類
接著就使用創(chuàng)建者模式創(chuàng)建一位應(yīng)聘者械哟,使用建造者類盯串,通過對(duì)這3個(gè)類組合調(diào)用,就可以創(chuàng)建出一個(gè)完整的應(yīng)聘者對(duì)象戒良。
實(shí)例代碼
/****
* 應(yīng)聘者建造者
* 參數(shù) name: 姓名(全名) 空格分隔姓名
* 參數(shù) work: 期望職位
**/
var Person = function(name, work){
// 創(chuàng)建應(yīng)聘者緩存對(duì)象
var _person = new Human();
// 創(chuàng)建應(yīng)聘者姓名解析對(duì)象
_person.name = new Named(name);
// 創(chuàng)建應(yīng)聘者期望職位
_person.work = new Work(work);
// 將創(chuàng)建的應(yīng)聘者對(duì)象返回
return _person;
}
- 在上面代碼中 我們分成了三個(gè)部分來創(chuàng)建一位應(yīng)聘者對(duì)象
- 首先創(chuàng)建一位應(yīng)聘者緩存對(duì)象,緩存對(duì)象需要修飾(添加屬性和方法)
- 然后我們向緩存對(duì)象添加姓名
- 最后添加一個(gè)職位冠摄,最終我們就可得到一位完整的應(yīng)聘者
測(cè)試代碼
var person = new Person('Sun Wukong', 'code');
console.log(person.skill) // 保密
console.log(person.name.firstName) // Sun
console.log(person.work.work) // 工程師
console.log(person.work.workDescript) // 每一天在編程中度過
person.work.changeDescript('更改一下職位描述糯崎!')
console.log(person.work.workDescript) // 更改一下職位描述!
總結(jié)
- 工廠模式創(chuàng)建出來的是一個(gè)對(duì)象河泳,追求的是創(chuàng)建的結(jié)果沃呢,是一個(gè)實(shí)實(shí)在在的創(chuàng)建結(jié)果(實(shí)例化始終是一個(gè)類的對(duì)象或者單一的繼承(抽象工廠方法))
- 創(chuàng)建者模式有所不同,不僅可以得到創(chuàng)建的結(jié)果拆挥,也參與了創(chuàng)建的具體過程薄霜,對(duì)于創(chuàng)建的具體實(shí)現(xiàn)的細(xì)節(jié)也參閱了干涉,創(chuàng)建的對(duì)象更復(fù)雜纸兔,這種模式創(chuàng)建的對(duì)象是一個(gè)復(fù)合對(duì)象(很像Java中一些復(fù)合類的實(shí)現(xiàn))
注意
- 工廠模式創(chuàng)建的結(jié)果都是一個(gè)完整的個(gè)體惰瓜,過程我們并不關(guān)心,只得到創(chuàng)建結(jié)果對(duì)象汉矿。
- 創(chuàng)建者模式中我們要關(guān)系對(duì)象創(chuàng)建的過程崎坊,通常會(huì)把創(chuàng)建對(duì)象的類模塊化,好處是洲拇,使被創(chuàng)建的類的每一個(gè)模塊都可以得到靈活的運(yùn)用與高質(zhì)量的復(fù)用奈揍,
- 但是最終需求是要得到一個(gè)完整的個(gè)體,所以在拆分創(chuàng)建的整個(gè)過程赋续,我們還是會(huì)得到一個(gè)統(tǒng)一的結(jié)果
- 這種方式對(duì)于整體對(duì)象類的拆分無形中增加了結(jié)構(gòu)的復(fù)雜性男翰,因此如果對(duì)象粒度很小,或者模塊間的復(fù)用率很低并且變動(dòng)不大纽乱,我們最好還是要?jiǎng)?chuàng)建整體對(duì)象
這篇文字有點(diǎn)多蛾绎,需要盡力去理解,還要對(duì)照前面的工廠模式來看