1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        設(shè)計模式之建造者模式(BuilderPattern)

        共 11743字,需瀏覽 24分鐘

         ·

        2021-03-20 10:13

        點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

        優(yōu)質(zhì)文章,第一時間送達(dá)

          作者 |  敲代碼的小小酥

        來源 |  urlify.cn/zmuaey

        76套java從入門到精通實(shí)戰(zhàn)課程分享

        一.意義

        將一個復(fù)雜的對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

        說明:復(fù)雜對象的構(gòu)建,比如一個對象有幾十個成員屬性,那么我們在創(chuàng)建這個對象,并給成員屬性賦值時,就會很麻煩。采用建造者模式,就是把創(chuàng)建對象并給成員屬性賦值的工作,分離出來,由建造者角色來完成,業(yè)務(wù)程序員直接調(diào)用導(dǎo)演類,獲得復(fù)雜對象即可,無需再進(jìn)行對象的創(chuàng)建工作了。

        二.角色

        建造者模式涉及到一下幾種角色:

        Builder(抽象建造者):它為創(chuàng)建一個產(chǎn)品Product對象的各個部件指定抽象接口,在該接口中一般聲明兩類方法,一類方法是buildPartX(),它們用于創(chuàng)建復(fù)雜對象的各個部件;另一類方法是getResult(),它們用于返回復(fù)雜對象。Builder既可以是抽象類,也可以是接口。由此可見,抽象建造者就類似于抽象工廠,只不過,抽象工廠是調(diào)度的產(chǎn)品的整體部件,而抽象建造者,是構(gòu)造產(chǎn)品的內(nèi)部部件。抽象建造者定義了建造規(guī)范,不同的建造者遵循著同樣的建造規(guī)范,構(gòu)建不同的部件。

        ConcreteBuilder(具體建造者):它實(shí)現(xiàn)了Builder接口,實(shí)現(xiàn)各個部件的具體構(gòu)造和裝配方法,定義并明確它所創(chuàng)建的復(fù)雜對象,也可以提供一個方法返回創(chuàng)建好的復(fù)雜產(chǎn)品對象。具體建造者就相當(dāng)于工廠實(shí)現(xiàn)類。一個產(chǎn)品,對應(yīng)一個具體建造者,構(gòu)造多樣的部件,并返回對應(yīng)的產(chǎn)品對象。

        Product(產(chǎn)品角色):它是被構(gòu)建的復(fù)雜對象,包含多個組成部件,具體建造者創(chuàng)建該產(chǎn)品的內(nèi)部表示并定義它的裝配過程。在建造者模式中,產(chǎn)品大多是一個類,產(chǎn)品的部件就是類的成員屬性。

        Director(指揮者):指揮者又稱為導(dǎo)演類,它負(fù)責(zé)安排復(fù)雜對象的建造次序,指揮者與抽象建造者之間存在關(guān)聯(lián)關(guān)系,可以在其construct()建造方法中調(diào)用建造者對象的部件構(gòu)造與裝配方法,完成復(fù)雜對象的建造??蛻舳艘话阒恍枰c指揮者進(jìn)行交互,在客戶端確定具體建造者的類型,并實(shí)例化具體建造者對象(也可以通過配置文件和反射機(jī)制),然后通過指揮者類的構(gòu)造函數(shù)或者Setter方法將該對象傳入指揮者類中。

        個人感覺,這里的導(dǎo)演類,完全可以融合到建造者角色中,這樣的話,對于調(diào)用者而言,選擇具體建造者的時候,通過建造者構(gòu)造部件,也可以獲得產(chǎn)品。這種形式,就是把產(chǎn)品的構(gòu)建和產(chǎn)品的獲得,都放到了一個類里,違反了單一責(zé)任原則。所以,導(dǎo)演類的存在,是為了滿足單一責(zé)任原則。那為什么在工廠模式中,沒有導(dǎo)演這個角色呢,那是因?yàn)樵诠S模式中,工廠的作用就是生產(chǎn)產(chǎn)品,直接通過工廠,就獲得了產(chǎn)品。而建造者模式,建造者是在構(gòu)建產(chǎn)品,它體現(xiàn)的是一個過程,而不是最終的結(jié)果。

        三、代碼實(shí)現(xiàn)

        我們來構(gòu)建上述的角色,實(shí)現(xiàn)建造者模式:

        首先,先定義產(chǎn)品,我們以電腦產(chǎn)品為例,建造者模式的產(chǎn)品以類為主,注重的是內(nèi)部的部件(成員屬性):

        /**
         * 產(chǎn)品:電腦
         */
        public class Computer {
            /**
             * 內(nèi)部部件:
             */
            private String brand;
            private String cpu;
            private String mainBoard;
            private String hardDisk;
            private String displayCard;
            private String power;
            private String memory;

            public String getBrand() {
                return brand;
            }

            public void setBrand(String brand) {
                this.brand = brand;
            }

            public String getCpu() {
                return cpu;
            }

            public void setCpu(String cpu) {
                this.cpu = cpu;
            }

            public String getMainBoard() {
                return mainBoard;
            }

            public void setMainBoard(String mainBoard) {
                this.mainBoard = mainBoard;
            }

            public String getHardDisk() {
                return hardDisk;
            }

            public void setHardDisk(String hardDisk) {
                this.hardDisk = hardDisk;
            }

            public String getDisplayCard() {
                return displayCard;
            }

            public void setDisplayCard(String displayCard) {
                this.displayCard = displayCard;
            }

            public String getPower() {
                return power;
            }

            public void setPower(String power) {
                this.power = power;
            }

            public String getMemory() {
                return memory;
            }

            public void setMemory(String memory) {
                this.memory = memory;
            }
        } 

        然后,我們定義抽象創(chuàng)建者,主要分為兩部分:buildX構(gòu)建部件,和getResult獲取構(gòu)建產(chǎn)品,代碼如下:

        **
         * 建造者角色,其實(shí)就是代替復(fù)雜對象的構(gòu)造函數(shù)等構(gòu)造方式,在這里對復(fù)雜對象進(jìn)行構(gòu)建
         */
        public abstract class ComputerBuilder {
            //建造者中,創(chuàng)建復(fù)雜產(chǎn)品對象,構(gòu)建出復(fù)雜對象后,進(jìn)行輸出。
            protected Computer computer = new Computer();

            /**
             * 建造產(chǎn)品部件的方法,這里用抽象方法,不同的建造者可以構(gòu)建出不同的產(chǎn)品部件來。
             */
            public abstract void buildBrand();
            public abstract void buildCPU();
            public abstract void buildMainBoard();
            public abstract void buildHardDisk();
            public abstract void buildDisplayCard();
            public abstract void buildPower();
            public abstract void buildMemory();

            /**
             * 建造者最后輸出復(fù)雜產(chǎn)品。
             * @return
             */
            public Computer createComputer() {
                return computer;
            }
        }

        然后創(chuàng)建具體建造者類,如下代碼:

        /**
         * 具體建造者,可以構(gòu)建不同的產(chǎn)品部件。構(gòu)建者有統(tǒng)一的構(gòu)建接口,這樣可以規(guī)范不同構(gòu)建者。
         */
        public class ASUSComputerBuilder extends ComputerBuilder{
            @Override
            public void buildBrand() {
                computer.setBrand("華碩電腦");
            }

            @Override
            public void buildCPU() {
                computer.setCpu("Intel 第8代 酷睿");
            }

            @Override
            public void buildMainBoard() {
                computer.setMainBoard("華碩主板");
            }

            @Override
            public void buildHardDisk() {
                computer.setHardDisk("256GB SSD");
            }

            @Override
            public void buildDisplayCard() {
                computer.setDisplayCard("MX150 獨(dú)立2GB");
            }

            @Override
            public void buildPower() {
                computer.setPower("3芯 鋰離子電池 65W AC適配器");
            }

            @Override
            public void buildMemory() {
                computer.setMemory("1 x SO-DIMM  8GB");
            }
        }
        /**
         * 具體建造者,可以構(gòu)建不同的產(chǎn)品部件。構(gòu)建者有統(tǒng)一的構(gòu)建接口,這樣可以規(guī)范不同構(gòu)建者。
         */
        public class DellComputerBuilder extends ComputerBuilder {
            @Override
            public void buildBrand() {
                computer.setBrand("戴爾電腦");
            }

            @Override
            public void buildCPU() {
                computer.setCpu("i5-8300H 四核");
            }

            @Override
            public void buildMainBoard() {
                computer.setMainBoard("戴爾主板");

            }

            @Override
            public void buildHardDisk() {
                computer.setHardDisk("1T + 128GB SSD");
            }

            @Override
            public void buildDisplayCard() {
                computer.setDisplayCard("GTX1060 獨(dú)立6GB");

            }

            @Override
            public void buildPower() {
                computer.setPower("4芯 鋰離子電池 180W AC適配器");
            }

            @Override
            public void buildMemory() {
                computer.setMemory("4G + 4G");
            }
        }

        然后,我們定義導(dǎo)演類,來調(diào)度建造者,輸出復(fù)雜產(chǎn)品:

        /**
         * 導(dǎo)演類,指揮構(gòu)建過程,調(diào)用建造者類。
         */
        public class ComputerDirector {
            /**
             * 導(dǎo)演類的建造方法一般都用construct命名。傳入具體建造者類,輸出產(chǎn)品
             * @param builder
             * @return
             */
            public Computer construct(ComputerBuilder builder){
                Computer computer;
                builder.buildBrand();
                builder.buildCPU();
                builder.buildDisplayCard();
                builder.buildHardDisk();
                builder.buildMainBoard();
                builder.buildMemory();
                builder.buildPower();
                computer = builder.createComputer();
                return computer;

            }
        }

        這樣,對于業(yè)務(wù)程序員而言,就可以通過導(dǎo)演類,來獲取復(fù)雜對象了,如下:

        public class Main {
            public static void main(String[] args) {
                //用戶直接使用的是導(dǎo)演類
               ComputerDirector director=new ComputerDirector();
               //選擇相應(yīng)的構(gòu)建者,來構(gòu)建不同的部件
                ComputerBuilder dellBuilder = new DellComputerBuilder();
                //返回構(gòu)建出來的產(chǎn)品
                Computer dellComputer=director.construct(dellBuilder);


            }
            
        }

        由此我們可以看到,業(yè)務(wù)程序員需要選擇具體的建造類,傳入導(dǎo)演類中,獲得產(chǎn)品。在我們實(shí)際項(xiàng)目中,通常我們在xml里定義需要的具體建造者類,然后spring等其他框架讀取我們在xml里寫的具體建造者類,調(diào)用導(dǎo)演類,來獲得程序員想要的產(chǎn)品。所以對于業(yè)務(wù)程序員而言,需要做的就是在xml里定義具體建造者,導(dǎo)演類都是框架在做。 

        四、優(yōu)點(diǎn)和缺點(diǎn)

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

        • 在建造者模式中,客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對象。

        • 每一個具體建造者都相對獨(dú)立,而與其他的具體建造者無關(guān),因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產(chǎn)品對象。由于指揮者類針對抽象建造者編程,增加新的具體建造者無須修改原有類庫的代碼,系統(tǒng)擴(kuò)展方便,符合 “開閉原則”。

        • 可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過程。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過程更加清晰,也更方便使用程序來控制創(chuàng)建過程。

        缺點(diǎn):

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

        • 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會導(dǎo)致需要定義很多具體建造者類來實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大,增加系統(tǒng)的理解難度和運(yùn)行成本。從這句話我們可以看出,在我們應(yīng)用設(shè)計模式時,也要考慮系統(tǒng)的復(fù)雜程度,即使一個業(yè)務(wù)很適合應(yīng)用某種設(shè)計模式,但是應(yīng)用起來,很笨重很復(fù)雜,那么我們也不建議生搬硬套設(shè)計模式。

        五、建造者模式的本質(zhì)

        建造者模式的本質(zhì),就是建造對象。我們在閱讀源碼中,看到Builder字樣時,只要知道其實(shí)在創(chuàng)造產(chǎn)品即可。具體其怎么走流程,怎么創(chuàng)建這個對象的,我們不用太過關(guān)注,因?yàn)橛行┙ㄔ煺吣J?,結(jié)構(gòu)和設(shè)計特別復(fù)雜。





        粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

        ??????

        ??長按上方微信二維碼 2 秒


        感謝點(diǎn)贊支持下哈 

        瀏覽 58
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            精品成人18秘 亚洲AV蜜臀 | 色婷婷激情电影 | 特级西西高清4Www电影 | 91嫩草精品少妇91嫩草影视剧 | 天堂成人在线 | 翔田千里无码破解版 | 国产不卡毛片 | 九九综合 | 天天操欧美网站 | 国产成人电影在线免费观看 |