<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          還沒(méi)用過(guò)建造者模式?這篇文章幫你搞定

          共 6731字,需瀏覽 14分鐘

           ·

          2021-06-24 07:42

          前言

          我們知道,常見(jiàn)的設(shè)計(jì)模式通常分為三大類(lèi):創(chuàng)建型模式、行為型模式、結(jié)構(gòu)型模式。今天我們來(lái)聊聊創(chuàng)建型模式中的建造者模式,關(guān)于它的使用場(chǎng)景、優(yōu)缺點(diǎn)、組成部分、實(shí)戰(zhàn)實(shí)例講解以及在JDK中的運(yùn)用。

          工廠模式我們已經(jīng)比較熟悉,主要用來(lái)將實(shí)例化對(duì)象提取出來(lái),放到一個(gè)類(lèi)中統(tǒng)一維護(hù)和管理,從而達(dá)到解耦、提高項(xiàng)目的擴(kuò)展性和維護(hù)性。建造者模式的功能與工廠模式很相似,但側(cè)重點(diǎn)不同。下面我們就來(lái)詳細(xì)了解一下創(chuàng)建者模式。

          建造者模式簡(jiǎn)介

          創(chuàng)建者模式(Builder Pattern),也翻譯作構(gòu)建者模式,也有人通俗的稱(chēng)作生成器模式。官方定義是:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。

          用大白話解釋就是:將一個(gè)復(fù)雜的對(duì)象分解為多個(gè)簡(jiǎn)單的對(duì)象,然后一步一步構(gòu)建形成產(chǎn)品。它主要是將變化部分與不變部分相分離,即產(chǎn)品的組成部分是不變的,但每一部分是可以靈活選擇的。

          就好比我們要組裝一臺(tái)電腦,需要 CPU、主板、內(nèi)存、硬盤(pán)、顯卡、機(jī)箱、顯示器、鍵盤(pán)、鼠標(biāo)等部件,這些部件是不變的,但根據(jù)自身經(jīng)濟(jì)情況和使用的場(chǎng)景不同,可選擇每部分的不同配置。

          像這么一個(gè)復(fù)雜的對(duì)象的構(gòu)建,往往需要多個(gè)步驟來(lái)進(jìn)行完成。而且每個(gè)步驟采用的硬件配置信息可能有所不同。同時(shí),也并不是每個(gè)電腦都需要顯示器或鼠標(biāo)的。在通過(guò)代碼演示上述場(chǎng)景之前,我們先來(lái)了解一下建造者模式通常包含的幾個(gè)角色及功能。

          結(jié)構(gòu)與功能

          建造者模式通常由四個(gè)角色組成:產(chǎn)品、抽象建造者、具體建造者、指揮者。

          每個(gè)角色功能如下:

          • 產(chǎn)品角色(Product):要?jiǎng)?chuàng)建的具體產(chǎn)品對(duì)象,通常是包含多個(gè)組成部件的復(fù)雜對(duì)象。

          • 抽象建造者(Builder):用于創(chuàng)建產(chǎn)品對(duì)象的接口或抽象類(lèi),其中包含創(chuàng)建產(chǎn)品各個(gè)子部件的抽象方法和返回最終最終對(duì)象的方法。

          • 具體建造者(Concrete Builder):實(shí)現(xiàn)Builder接口,完成不同復(fù)雜產(chǎn)品構(gòu)建和裝配。

          • 指揮者(Director):構(gòu)建一個(gè)使用Builder接口的對(duì)象,完成復(fù)雜對(duì)象的創(chuàng)建。它負(fù)責(zé)控制產(chǎn)品對(duì)象的生產(chǎn)過(guò)程,同時(shí)隔離了用戶與對(duì)象的產(chǎn)生過(guò)程。在指揮者中不涉及具體產(chǎn)品的信息。

          結(jié)構(gòu)圖如圖所示:

          模式的實(shí)現(xiàn)

          作為開(kāi)發(fā)人員,我們使用筆記本時(shí),往往還會(huì)配置外置鍵盤(pán)、鼠標(biāo)和外置顯示器。此時(shí),一整套電腦裝備就包含了:筆記本電腦、鼠標(biāo)、鍵盤(pán)、顯示器。當(dāng)然,根據(jù)個(gè)人的需求不同,有些人不需要鼠標(biāo),有些人不需要外置鍵盤(pán),有些人不需要外置顯示器,這就又構(gòu)成了不同的產(chǎn)品。

          先來(lái)定義產(chǎn)品類(lèi)Computer,也就是開(kāi)發(fā)電腦的整體配置:

          public class Computer {

          /**
          * 筆記本電腦
          */

          private Laptop laptop;

          /**
          * 鼠標(biāo)
          */

          private Mouse mouse;

          /**
          * 顯示器
          */

          private Screen screen;

          /**
          * 鍵盤(pán)
          */

          private Keyboard keyboard;

          public void show() {
          System.out.println("筆記本配置:" + laptop.getName());
          System.out.println("鼠標(biāo)配置:" + mouse.getName());
          System.out.println("顯示器配置:" + screen.getName());
          System.out.println("鍵盤(pán)配置:" + keyboard.getName());
          }

          // 省略getter/setter方法
          }

          產(chǎn)品由四個(gè)組件構(gòu)成:筆記本電腦、鼠標(biāo)、顯示器、鍵盤(pán)。

          抽象建造者:包含創(chuàng)建產(chǎn)品各個(gè)子部件的抽象方法。通過(guò)接口聲明在所有類(lèi)型生成器中通用的產(chǎn)品構(gòu)造步驟。

          public interface ComputerBuilder {

          /**
          * 構(gòu)建筆記本電腦
          */

          void constructLaptop();

          /**
          * 構(gòu)建鼠標(biāo)
          */

          void constructMouse();

          /**
          * 構(gòu)建屏幕
          */

          void constructScreen();

          /**
          * 構(gòu)建鍵盤(pán)
          */

          void constructKeyboard();

          /**
          * 返回最終產(chǎn)品對(duì)象
          */

          Computer getResult();
          }

          抽象建造者提供了每個(gè)組件構(gòu)建的統(tǒng)一方法,至于具體每個(gè)組件內(nèi)部的配置可能會(huì)有各種各樣的變化,這就有具體的實(shí)現(xiàn)者來(lái)實(shí)現(xiàn)。

          具體建造者:實(shí)現(xiàn)了抽象建造者接口。在當(dāng)前業(yè)務(wù)場(chǎng)景中,我們假設(shè)公司給的電腦配置有兩類(lèi),一類(lèi)是普通的配置,一類(lèi)是高端配置。這樣就有兩個(gè)具體的建造者了,用來(lái)提供構(gòu)造過(guò)程的不同實(shí)現(xiàn)。

          普通配置實(shí)現(xiàn):

          public class CommonComputerBuilder implements ComputerBuilder {

          private Computer computer = new Computer();

          @Override
          public void constructLaptop() {
          Laptop laptop = new Laptop("A","華為筆記本");
          computer.setLaptop(laptop);
          }

          @Override
          public void constructMouse() {
          Mouse mouse = new Mouse("A","無(wú)線鼠標(biāo)");
          computer.setMouse(mouse);
          }

          @Override
          public void constructScreen() {
          Screen screen = new Screen("A","液晶顯示器");
          computer.setScreen(screen);
          }

          @Override
          public void constructKeyboard() {
          Keyboard keyboard = new Keyboard("A","普通鍵盤(pán)");
          computer.setKeyboard(keyboard);
          }

          @Override
          public Computer getResult() {
          return computer;
          }
          }

          高級(jí)配置實(shí)現(xiàn):

          public class SupperComputerBuilder implements ComputerBuilder {

          private Computer computer = new Computer();

          @Override
          public void constructLaptop() {
          Laptop laptop = new Laptop("S", "Mac Boor Pro");
          computer.setLaptop(laptop);
          }

          @Override
          public void constructMouse() {
          Mouse mouse = new Mouse("A", "無(wú)線鼠標(biāo)");
          computer.setMouse(mouse);
          }

          @Override
          public void constructScreen() {
          Screen screen = new Screen("S", "液晶曲面屏");
          computer.setScreen(screen);
          }

          @Override
          public void constructKeyboard() {
          Keyboard keyboard = new Keyboard("S", "機(jī)械鍵盤(pán)");
          computer.setKeyboard(keyboard);
          }

          @Override
          public Computer getResult() {
          return computer;
          }
          }

          在此具體建造者中,設(shè)置了每個(gè)組件的配置信息,這里做了簡(jiǎn)化,每個(gè)組件都只有類(lèi)型和名稱(chēng)。而實(shí)際使用中,可能每個(gè)組件對(duì)象會(huì)包含不同的數(shù)據(jù)項(xiàng)。

          指揮者:調(diào)用建造者中的方法完成復(fù)雜對(duì)象的創(chuàng)建。

          public class Director {

          private ComputerBuilder builder;

          public Director(ComputerBuilder builder) {
          this.builder = builder;
          }

          //產(chǎn)品構(gòu)建與組裝方法
          public Computer construct() {
          builder.constructLaptop();
          builder.constructMouse();
          builder.constructScreen();
          builder.constructKeyboard();
          return builder.getResult();
          }
          }

          指揮者對(duì)整個(gè)生產(chǎn)過(guò)程進(jìn)行了封裝,對(duì)客戶端進(jìn)行了隔離,客戶端只用獲得最終的產(chǎn)品即可,不用關(guān)心組裝的過(guò)程。

          客戶端調(diào)用示例:

          public class Client {

          public static void main(String[] args) {

          // 普通配置電腦的組裝
          ComputerBuilder builder = new CommonComputerBuilder();
          Director director = new Director(builder);
          Computer product = director.construct();
          product.show();

          System.out.println("------------------");

          // 高級(jí)配置電腦的組裝
          builder = new SupperComputerBuilder();
          director = new Director(builder);
          product = director.construct();
          product.show();

          // 可拓展其他配置的構(gòu)建中實(shí)現(xiàn)

          }
          }

          執(zhí)行程序打印結(jié)果如下:

          筆記本配置:華為筆記本
          鼠標(biāo)配置:無(wú)線鼠標(biāo)
          顯示器配置:液晶顯示器
          鍵盤(pán)配置:普通鍵盤(pán)
          ------------------

          筆記本配置:Mac Boor Pro
          鼠標(biāo)配置:無(wú)線鼠標(biāo)
          顯示器配置:液晶曲面屏
          鍵盤(pán)配置:機(jī)械鍵盤(pán)

          針對(duì)上述實(shí)例,我們可以發(fā)現(xiàn),如果還需要其他配置的電腦,只需要再創(chuàng)建一個(gè)Builder實(shí)現(xiàn)類(lèi)即可,而指導(dǎo)類(lèi)的組裝順序等也可以進(jìn)行調(diào)整。在這種情況下對(duì)原有的功能也不會(huì)造成影響,符合設(shè)計(jì)模式中的開(kāi)閉原則。

          應(yīng)用場(chǎng)景

          適用場(chǎng)景其實(shí)才是理解設(shè)計(jì)模式最重要的,只有知道了適用于什么場(chǎng)景,才能夠準(zhǔn)確的使用設(shè)計(jì)模式。

          根據(jù)上述實(shí)例可以看出,建造者(Builder)模式創(chuàng)建的是復(fù)雜對(duì)象,適用于面向產(chǎn)品的各個(gè)具體部分經(jīng)常出現(xiàn)變化,但將它們組合在一起的算法卻相對(duì)穩(wěn)定的場(chǎng)景。

          建造者模式適用于以下場(chǎng)景:

          • 創(chuàng)建的對(duì)象較復(fù)雜,由多個(gè)部件構(gòu)成,各部件面臨著復(fù)雜的變化,但構(gòu)件間的建造順序是穩(wěn)定的,產(chǎn)生的結(jié)果又不相同。

          • 產(chǎn)品類(lèi)非常復(fù)雜,或者產(chǎn)品類(lèi)中不同的調(diào)用順序產(chǎn)生不同的作用;

          • 需要?jiǎng)?chuàng)建的各種形式的產(chǎn)品, 它們的制造過(guò)程相似且僅有細(xì)節(jié)上的差異;

          • 使用生成器構(gòu)造組合樹(shù)或其他復(fù)雜對(duì)象,建造者模式可以分步、延時(shí)構(gòu)造產(chǎn)品;

          • 構(gòu)造函數(shù)中有N個(gè)可選參數(shù),那new各種實(shí)例比較麻煩,需要重載構(gòu)造函數(shù)多次,而且很多參數(shù)都具有默認(rèn)值。

          優(yōu)點(diǎn)與缺點(diǎn)

          通過(guò)上面的介紹,大概就可以了解到建造者模式的優(yōu)缺點(diǎn)了。

          優(yōu)點(diǎn):

          • 各個(gè)具體的建造者相互獨(dú)立,可以很方便地替換具體建造者或增加新的具體建造者,有利于系統(tǒng)的擴(kuò)展。

          • 封裝性好,構(gòu)建和表示分離,客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),便于控制細(xì)節(jié)風(fēng)險(xiǎn)。

          • 可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過(guò)程,建造者可以對(duì)創(chuàng)建過(guò)程逐步細(xì)化,而不對(duì)其他模塊產(chǎn)生任何影響。

          建造者模式的缺點(diǎn):

          • 需要多創(chuàng)建額外的Builder接口和實(shí)現(xiàn)類(lèi);

          • 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會(huì)導(dǎo)致需要定義很多具體建造者類(lèi)來(lái)實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大;

          • 如果產(chǎn)品內(nèi)部發(fā)生變化,建造者也要同步修改,后期維護(hù)成本較大。

          • 建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點(diǎn),其組成部分相似,如果產(chǎn)品之間的差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制;

          建造者(Builder)模式在應(yīng)用過(guò)程中可以根據(jù)需要改變,如果創(chuàng)建的產(chǎn)品種類(lèi)只有一種,只需要一個(gè)具體建造者,這時(shí)可以省略掉抽象建造者,甚至可以省略掉指揮者角色。

          工廠模式VS建造者模式

          建造者(Builder)模式和工廠模式的關(guān)注點(diǎn)不同:建造者模式注重零部件的組裝過(guò)程,而工廠方法模式更注重零部件的創(chuàng)建過(guò)程,兩者可以結(jié)合使用。

          建造者模式和工廠模式的區(qū)別: 

          (1)建造者模式更加注重方法的調(diào)用順序,工廠模式注重創(chuàng)建對(duì)象; 

          (2)創(chuàng)建對(duì)象的力度不同,建造者模式創(chuàng)建復(fù)雜的對(duì)象,有各種復(fù)雜的部件組成,工廠模式創(chuàng)建出來(lái)的對(duì)象都一樣; 

          (3)關(guān)注重點(diǎn)不一樣,工廠模式只需要把對(duì)象創(chuàng)建出來(lái)就可以了,而建造者模式不僅要?jiǎng)?chuàng)建出對(duì)象,還需要知道對(duì)象由哪些部件組成; 

          (4)建造者模式根據(jù)建造過(guò)程中順序的不一樣,最終的對(duì)象部件組成也不一樣。

          JDK中建造者的應(yīng)用

          我們最常用的StringBuilder類(lèi)中就有建造者模式最直接的應(yīng)用,看一下核心代碼:

          public AbstractStringBuilder append(String str) {
          if (str == null)
          return appendNull();
          int len = str.length();
          ensureCapacityInternal(count + len);
          str.getChars(0, len, value, count);
          count += len;
          return this;
          }

          @Override
          public StringBuilder append(char c) {
          super.append(c);
          return this;
          }

          關(guān)于StringBuilder具體的接口繼承等功能實(shí)現(xiàn),可以對(duì)照上面的說(shuō)明看一下源碼實(shí)現(xiàn)。

          小結(jié)

          本篇文章帶大家實(shí)踐了一下建造者模式,詳細(xì)介紹了它的構(gòu)成與每部分的功能。關(guān)于設(shè)計(jì)模式,最重要的一點(diǎn)就是理解它們的應(yīng)用場(chǎng)景,在適合的場(chǎng)景下使用合適的設(shè)計(jì)模式,同時(shí)還可以根據(jù)具體環(huán)境進(jìn)行靈活的變通。


          往期推薦

          軟件架構(gòu)分層,你的項(xiàng)目處于什么階段?

          一篇文章,只用看三遍,終生不忘網(wǎng)絡(luò)分層!

          一篇文章,領(lǐng)略Java8中ConcurrentHashMap的方方面面

          萬(wàn)字解讀Java線程池設(shè)計(jì)思想及源碼實(shí)現(xiàn)

          監(jiān)聽(tīng)器模式和觀察者模式的關(guān)系,寫(xiě)點(diǎn)你不知道的



          如果你覺(jué)得這篇文章不錯(cuò),那么,下篇通常會(huì)更好。添加微信好友,可備注“加群”(微信號(hào):zhuan2quan)

          一篇文章就看透技術(shù)本質(zhì)的人,
            和花一輩子都看不清的人,
            注定是截然不同的搬磚生涯。
          ▲ 長(zhǎng)按關(guān)注”程序新視界“,洞察技術(shù)內(nèi)幕


          瀏覽 78
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情四月五月婷婷小电影 | 另类天堂| 天天撸天天操 | 欧美日韩精品久久久免费观看 | 亚洲乱伦小说网站 |