JavaScript設(shè)計模式——建造者模式

寫在前面

早該更新文章了宴倍,然而最近深陷項(xiàng)(囹)目(圄)张症。為了適配萬惡的IE8,不得不使用陳舊的框架Ext鸵贬,從未接觸過俗他,純英文的文檔,心中的苦悶自是不得而知阔逼。因此兆衅,拖拖沓沓,迎來了久違的建造者模式嗜浮。

什么是建造者模式

將一個復(fù)雜對象的構(gòu)建層與其表現(xiàn)層相互分離羡亩,同樣的構(gòu)建過程可以采用不同的表示。

當(dāng)我們創(chuàng)建一個復(fù)雜的對象時危融,我們需要更多的關(guān)心創(chuàng)建這個對象的整個過程畏铆,甚至是創(chuàng)建對象的每一個細(xì)節(jié)。那這個時候专挪,我們使用建造者模式及志,在這個模式中,有一個指揮者寨腔,一個建造者速侈,由指導(dǎo)者來管理建造者,用戶是與指導(dǎo)者聯(lián)系的迫卢,指導(dǎo)者聯(lián)系建造者最后得到產(chǎn)品倚搬。主要用于“分步驟構(gòu)建一個復(fù)雜的對象”。

四要素

1.產(chǎn)品類Product:一般是一個較為復(fù)雜的對象乾蛤,也就是說創(chuàng)建對象的過程比較復(fù)雜每界,一般會有比較多的代碼量。
2.抽象建造者類Builder: 將建造的具體過程交與它的子類來實(shí)現(xiàn)家卖,這樣更容易擴(kuò)展眨层。
3.建造者類ConcreteBuilder: 組建產(chǎn)品;返回組建好的產(chǎn)品上荡。
4.指導(dǎo)類Director: 負(fù)責(zé)調(diào)用適當(dāng)?shù)慕ㄔ煺邅斫M建產(chǎn)品趴樱,指導(dǎo)類一般不與產(chǎn)品類發(fā)生依賴關(guān)系,與指導(dǎo)類直接交互的是建造者類

舉個栗子??

// 產(chǎn)品類
class Car {
    constructor() {
      this.frame = false;
      this.engine = false;
      this.wheel = false;
    }
}

// 建造者
class CarBuilder extends Car{
    constructor(name) {
      super();
      this.name = name;
    }
    
    buildFrame() {
      this.frame = true;
      console.log('??車框架搭建完畢');
      return this;
    }

    buildEngine() {
      this.engine = true;
      console.log('??引擎制造完畢');
      return this;
    }

    buildWheel() {
      this.wheel = true;
      console.log('??車轱轆制造完畢');
      return this;
    }
    
    build() {
      console.log(this.name + '??車拼裝完成?')
      return {
        name: this.name,
        frame: this.frame,
        engine: this.engine,
        wheel: this.wheel
      }
    }
}

// 指揮者
class Director {
    constructor(builder) {
      this.action = (builder) => {
        builder.buildFrame();
        builder.buildEngine();
        builder.buildWheel();
        builder.build();
      }
    }
}

let carBuilder = new CarBuilder('保時捷');
let director = new Director();
director.action(carBuilder)

我們可以看到,一個零件叁征,對應(yīng)會有一個制造該零件的方法纳账,每次都要去寫一個方法,顯得很浪費(fèi)時間捺疼,又多余疏虫。我們可以對此做簡化:

// 產(chǎn)品類
class Car {
  constructor() {
    this.frame = false;
    this.engine = false;
    this.wheel = false;
  }
}

// 建造者
class CarBuilder extends Car {
  constructor(name) {
    super();

    Object.keys(this).forEach(key => {
      const buildName = `build${key
        .substring(0, 1)
        .toUpperCase()}${key.substring(1)}`;
      this[buildName] = () => {
        console.log("汽車??零件" + key + "制造完成");
        this[key] = true;
      };
      return this;
    });
    this.name = name;
  }

  build() {
    console.log(this.name + "??車拼裝完成?");
    return {
      name: this.name,
      frame: this.frame,
      engine: this.engine,
      wheel: this.wheel
    };
  }
}

// 指揮者
class Director {
  constructor(builder) {
    this.action = builder => {
      builder.buildFrame();
      builder.buildEngine();
      builder.buildWheel();
      builder.build();
    };
  }
}

let carBuilder = new CarBuilder("保時捷");
let director = new Director();
director.action(carBuilder);

同樣的,對于build()方法啤呼,我們也可以利用這種方式卧秘,進(jìn)行精簡:

// 產(chǎn)品類
class Car {
  constructor() {
    this.frame = false;
    this.engine = false;
    this.wheel = false;
  }
}

// 建造者
class CarBuilder extends Car {
  constructor(name) {
    super();

    Object.keys(this).forEach(key => {
      const buildName = `build${key
        .substring(0, 1)
        .toUpperCase()}${key.substring(1)}`;
      this[buildName] = () => {
        console.log("汽車??零件" + key + "制造完成");
        this[key] = true;
      };
      return this;
    });
    this.name = name;
  }

  build() {
    console.log(this.name + "??車拼裝完成?");
    const keysNoBuilders = Object.keys(this).filter(key => typeof this[key] !== 'function');

    return keysNoBuilders.reduce((returnValue, key) => {
      return {
        ...returnValue,
        [key]: this[key]
      }
    }, {})
  }
}

// 指揮者
class Director {
  constructor(builder) {
    this.action = builder => {
      for (const key in builder) {
        builder.hasOwnProperty(key) &&
          typeof builder[key] === "function" &&
          builder[key]();
      }
      builder.build();
    };
  }
}

let carBuilder = new CarBuilder("保時捷");
let director = new Director();
director.action(carBuilder);

最后

更新不易,且讀且珍惜媳友。??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斯议,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子醇锚,更是在濱河造成了極大的恐慌哼御,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焊唬,死亡現(xiàn)場離奇詭異恋昼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赶促,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門液肌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸥滨,你說我怎么就攤上這事嗦哆。” “怎么了婿滓?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵老速,是天一觀的道長。 經(jīng)常有香客問我凸主,道長橘券,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任卿吐,我火速辦了婚禮旁舰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗡官。我一直安慰自己箭窜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布衍腥。 她就那樣靜靜地躺著绽快,像睡著了一般芥丧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坊罢,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天,我揣著相機(jī)與錄音擅耽,去河邊找鬼活孩。 笑死,一個胖子當(dāng)著我的面吹牛乖仇,可吹牛的內(nèi)容都是我干的憾儒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼乃沙,長吁一口氣:“原來是場噩夢啊……” “哼起趾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起警儒,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤训裆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜀铲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體边琉,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年记劝,在試婚紗的時候發(fā)現(xiàn)自己被綠了变姨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡厌丑,死狀恐怖定欧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怒竿,我是刑警寧澤砍鸠,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站愧口,受9級特大地震影響睦番,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜耍属,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一托嚣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厚骗,春花似錦示启、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迟螺。三九已至,卻和暖如春舍咖,著一層夾襖步出監(jiān)牢的瞬間矩父,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工排霉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窍株,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓攻柠,卻偏偏與公主長得像球订,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瑰钮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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