學(xué)習(xí)JavaScript設(shè)計(jì)模式——建造者模式

建造者模式——分即是合

建造者模式: 將一個(gè)復(fù)雜對(duì)象的構(gòu)建層與其表示層相互分離,同樣的構(gòu)造過(guò)程可采用不同的表示。

對(duì)比

  • 工廠模式主要是為了創(chuàng)建對(duì)象實(shí)例或者類簇(抽象工廠),關(guān)心的是最終產(chǎn)出(創(chuàng)建)的是什么

  • 工廠模式不關(guān)心創(chuàng)建的整個(gè)過(guò)程,僅僅需要知道最終的創(chuàng)建結(jié)果,通過(guò)工廠模式得到的都是對(duì)象實(shí)例或者類簇

  • 建造者模式在創(chuàng)建對(duì)象時(shí)更為復(fù)雜,雖然目的也是為了創(chuàng)建對(duì)象,但是這個(gè)模式更多關(guān)心的是創(chuàng)建這個(gè)對(duì)象的整個(gè)過(guò)程(比如創(chuàng)建一個(gè)人,我們創(chuàng)建的結(jié)果不僅僅是要得到人的實(shí)例,還要關(guān)注創(chuàng)建人的時(shí)候,這個(gè)人應(yīng)該穿什么衣服,男的還是女的,興趣愛(ài)好都是什么), 所以建造者模式更注重的是創(chuàng)建的的細(xì)節(jié)。

  • 比如在發(fā)布簡(jiǎn)歷的需求中,我們需要的不僅僅是應(yīng)聘者的一個(gè)實(shí)例,還要在創(chuàng)建過(guò)程中注意一下這位應(yīng)聘者都有哪些興趣愛(ài)好、他的姓名等信息,他所期望的職位是什么,等等,這些細(xì)節(jié)關(guān)注點(diǎn)都需要我們創(chuàng)建。

首先,需要的人類的類,和人類的姓名類、職位類等(在類里使用閉包,可以讓這個(gè)閉包既是閉包,又是這個(gè)類的構(gòu)造函數(shù))

  // 創(chuàng)建一位人類
  var Human = function(param){
     // 技能
     this.skill = param && param.skill || '保密';
     // 興趣愛(ài)好
     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ù)中通過(guò)傳入的職位特征來(lái)設(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 = '分享也是一種快樂(lè)';
          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)建了抽象出來(lái)的三個(gè)類——應(yīng)聘者類、姓名解析類與期望職位類

  • 接著就使用創(chuàng)建者模式創(chuàng)建一位應(yīng)聘者,使用建造者類,通過(guò)對(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è)部分來(lái)創(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)  // 每一天在編程中度過(guò)
 person.work.changeDescript('更改一下職位描述!')
 console.log(person.work.workDescript)  // 更改一下職位描述!
 

總結(jié)

  • 工廠模式創(chuàng)建出來(lái)的是一個(gè)對(duì)象,追求的是創(chuàng)建的結(jié)果,是一個(gè)實(shí)實(shí)在在的創(chuàng)建結(jié)果(實(shí)例化始終是一個(gè)類的對(duì)象或者單一的繼承(抽象工廠方法))
  • 創(chuàng)建者模式有所不同,不僅可以得到創(chuàng)建的結(jié)果,也參與了創(chuàng)建的具體過(guò)程,對(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ò)程我們并不關(guān)心,只得到創(chuàng)建結(jié)果對(duì)象。
  • 創(chuàng)建者模式中我們要關(guān)系對(duì)象創(chuàng)建的過(guò)程,通常會(huì)把創(chuàng)建對(duì)象的類模塊化,好處是,使被創(chuàng)建的類的每一個(gè)模塊都可以得到靈活的運(yùn)用與高質(zhì)量的復(fù)用,
  • 但是最終需求是要得到一個(gè)完整的個(gè)體,所以在拆分創(chuàng)建的整個(gè)過(guò)程,我們還是會(huì)得到一個(gè)統(tǒng)一的結(jié)果
  • 這種方式對(duì)于整體對(duì)象類的拆分無(wú)形中增加了結(jié)構(gòu)的復(fù)雜性,因此如果對(duì)象粒度很小,或者模塊間的復(fù)用率很低并且變動(dòng)不大,我們最好還是要?jiǎng)?chuàng)建整體對(duì)象

這篇文字有點(diǎn)多,需要盡力去理解,還要對(duì)照前面的工廠模式來(lái)看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容