設(shè)計(jì)模式(六)——建造者模式

本文屬于系列文章《設(shè)計(jì)模式》,附上文集鏈接

建造者模式

  • 定義:將一個(gè)復(fù)雜的對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
  • 要解決的問題:看定義就看到了,首先,針對(duì)的問題是復(fù)雜對(duì)象的構(gòu)建,其次,對(duì)這些復(fù)雜的構(gòu)建還可以存在不同的結(jié)果。
  • 屬于創(chuàng)建類模式

舉個(gè)栗子

builder,看到這個(gè)詞的第一印象就是工地里的建造者(最近剛好學(xué)校新建宿舍樓,天天見),然后嘛,工人要做的事,就是要建一棟宿舍樓,這就是構(gòu)建一個(gè)復(fù)雜的對(duì)象。而建宿舍這件事的構(gòu)建過程是相同的,但是新建的宿舍樓是要男女混住的,里面的具體構(gòu)造還不一樣(女生宿舍樓梯口裝攝像頭防狼賊。。),宿舍名也不一樣,所以相同的構(gòu)造過程得到不同的結(jié)果,就來實(shí)現(xiàn)這個(gè)栗子來玩一下。
要注意到的是,這里的明確需求,只是得到一個(gè)宿舍樓。

先用一下假設(shè)性原則,不然都體會(huì)不了這個(gè)模式的好處,我們先假設(shè),不用這個(gè)模式要怎么實(shí)現(xiàn)這個(gè)需求。
代碼:

// 抽象宿舍類,定義宿舍樓具有的幾個(gè)屬性
public abstract class Dormitory {
    // 地基
    protected String foundation;
    // 宿舍的攝像頭
    protected String cameraOnStairway;
    // 是否需要裝攝像頭要
    protected boolean needCamera;
    // 宿舍顏色
    protected String dormitoryColor;
    public void setFoundation(String foundation) {
        this.foundation = foundation;
    }
    public void setCameraOnStairway(String cameraOnStairway) {
        if(needCamera == true){
            this.cameraOnStairway = cameraOnStairway;
        }
    }
    public void setNeedCamera(boolean needCamera) {
        this.needCamera = needCamera;
    }
    public void setDormitoryColor(String dormitoryColor) {
        this.dormitoryColor = dormitoryColor;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("這個(gè)"+this.getClass().getSimpleName()+"宿舍樓,");
        sb.append(foundation+",");
        if(needCamera == true){
            sb.append(cameraOnStairway+",");
        }else{
            sb.append("不需要裝攝像頭,");
        }
        sb.append(dormitoryColor);
        return sb.toString();
    }
}
**********
// 男生宿舍
public class ManDormitory extends Dormitory{}
// 女生宿舍
public class WomanDormitory extends Dormitory {}
***********
// 場(chǎng)景類
public class Client {
    public static void main(String[] args) {
        Dormitory manDormitory = new ManDormitory();
        manDormitory.setFoundation("打了一個(gè)堅(jiān)實(shí)的地基");
        manDormitory.setNeedCamera(false);
        manDormitory.setCameraOnStairway("裝了一個(gè)攝像頭");
        manDormitory.setDormitoryColor("外表是酷酷的藍(lán)色");
        System.out.println(manDormitory);
        System.out.println("-------------------------------------");
        Dormitory womanDormitory = new WomanDormitory();
        womanDormitory.setFoundation("打了一個(gè)堅(jiān)實(shí)的地基");
        womanDormitory.setNeedCamera(true);
        womanDormitory.setCameraOnStairway("裝了一個(gè)酷酷的攝像頭");
        womanDormitory.setDormitoryColor("外表是萌萌的粉色");
        System.out.println(womanDormitory);
    }
}
結(jié)果:
這個(gè)ManDormitory宿舍樓,打了一個(gè)堅(jiān)實(shí)的地基,不需要裝攝像頭,外表是酷酷的藍(lán)色
-------------------------------------
這個(gè)WomanDormitory宿舍樓,打了一個(gè)堅(jiān)實(shí)的地基,裝了一個(gè)酷酷的攝像頭,外表是萌萌的粉色

如無意外,到這里可能就看下去了,因?yàn)檫@完全不是建造者模式,完全是一個(gè)new。但我問一句,如果沒看設(shè)計(jì)模式的東西,會(huì)覺得這個(gè)東西有很大很大的問題嗎?對(duì)嘛,初學(xué)者,誰(shuí)新建對(duì)象不是new的,得到結(jié)果就行了,完全不考慮擴(kuò)展。
在這里我很想說一句話就是,設(shè)計(jì)模式和面向?qū)ο蟮臇|西,首先要明白面向?qū)ο罅笤瓌t出現(xiàn)的目的是什么,要解決什么問題,否則,設(shè)計(jì)模式不就成了迂腐的教規(guī)了?面向?qū)ο笫菫榱烁玫慕鉀Q需求變化的問題, 然后在變化的點(diǎn),采用方法去擁抱這些變化。這才是最要緊要記住一個(gè)東西。所有的設(shè)計(jì)模式或者面向?qū)ο蟮乃性瓌t都是奔向這個(gè)目的而去的。
看回代碼,在上面例子那里我就說了,要明確清楚的是,需求,只是得到宿舍樓,所以在場(chǎng)景類那里,直接new了男女兩個(gè)宿舍,也并沒有什么問題,確實(shí)實(shí)現(xiàn)了需求。但是考慮到變化的情況,假如有的男生宿舍樓處于學(xué)校外圍,經(jīng)常被盜,需要裝攝像頭,而有的女生宿舍處于學(xué)校中心,太安全了,不需要裝攝像頭,怎么辦?這個(gè)就是需求變化的點(diǎn),而如果使用上面那套代碼,我們只能在場(chǎng)景類那里再new對(duì)象。每出現(xiàn)一個(gè)不同構(gòu)建過程的對(duì)象,我們就new一個(gè),瘋狂new,問題就是這個(gè),擴(kuò)展性極其差。

來用一下建造者模式

// 抽象建造類
public abstract class Builder {
    protected Dormitory dormitory;
    public abstract Dormitory buildDormitory();
}
// 負(fù)責(zé)建造男生宿舍的工人
public class ManDormitoryBuilder extends Builder{
    public ManDormitoryBuilder() {
        super.dormitory = new ManDormitory();
    }
    @Override
    public Dormitory buildDormitory() {
        super.dormitory.setFoundation("打了一個(gè)堅(jiān)實(shí)的地基");
        super.dormitory.setNeedCamera(false);
        super.dormitory.setCameraOnStairway("裝了一個(gè)攝像頭");
        super.dormitory.setDormitoryColor("外表是酷酷的藍(lán)色");
        return super.dormitory;
    }
}
// 負(fù)責(zé)建造女生宿舍的工人
public class WomanDormitoryBuilder extends Builder{
    public WomanDormitoryBuilder() {
        super.dormitory = new WomanDormitory();
    }
    @Override
    public Dormitory buildDormitory() {
        super.dormitory.setFoundation("打了一個(gè)堅(jiān)實(shí)的地基");
        super.dormitory.setNeedCamera(true);
        super.dormitory.setCameraOnStairway("裝了一個(gè)酷酷的攝像頭");
        super.dormitory.setDormitoryColor("外表是萌萌的粉色");
        return super.dormitory;
    }
}
// 宿舍類都沒有變化,這里就不列出來了
// 場(chǎng)景類
public class Client {
    public static void main(String[] args) {
        Builder manDormitoryBuilder = new ManDormitoryBuilder();
        Dormitory manDormitory = manDormitoryBuilder.buildDormitory();
        System.out.println(manDormitory);
        System.out.println("---------------");
        Builder womanDormitoryBuilder = new WomanDormitoryBuilder();
        Dormitory womanDormitory = womanDormitoryBuilder.buildDormitory();
        System.out.println(womanDormitory);
    }
}
結(jié)果:
這個(gè)ManDormitory宿舍樓,打了一個(gè)堅(jiān)實(shí)的地基,不需要裝攝像頭,外表是酷酷的藍(lán)色
\--------------------
這個(gè)WomanDormitory宿舍樓,打了一個(gè)堅(jiān)實(shí)的地基,裝了一個(gè)酷酷的攝像頭,外表是萌萌的粉色

分析下代碼:我們將new對(duì)象的過程封裝到builder那里,builder類里有個(gè)dormitory屬性,在子類builder構(gòu)造函數(shù)予以實(shí)現(xiàn),確保子類builder是對(duì)應(yīng)的dormitory的生產(chǎn)對(duì)象。然后在子類builder的buildDormitory方法實(shí)現(xiàn)dormitory的構(gòu)造過程。這么做有什么好處呢?我們的上層模塊Client以后再面對(duì)下層模塊Dormitory的變化時(shí),就不用做出太大的改動(dòng)了,比如上文中提到的新建兩種宿舍,我們可以怎么做?可以直接在子類中重載方法buildDormitory,傳入boolean參數(shù)來控制裝不裝攝像頭,也可以直接在子類加方法,怎樣的都行(擴(kuò)展性啥的各自考慮啦),然后我們的上層模塊Client都不需要再對(duì)這個(gè)Dormitory的構(gòu)建過程有很大的了解(迪米特法則),我們只需要在Client中做好與Builder的“交涉”即可。

后言:看了幾篇博客,發(fā)現(xiàn)還是沒看書這么好,博客往往直接將模式交代了就沒了。還有發(fā)現(xiàn)一件事,就是看到有博客下面有評(píng)論說例子不正確啥的,但是我看了之后,其實(shí)無非就是方法的實(shí)現(xiàn)沒有抽象好而已,而設(shè)計(jì)模式那個(gè)思想還是在那里的。所以我提醒自己,設(shè)計(jì)模式是一種思想,是一種方法,不是API這樣的方法,API根據(jù)參數(shù),能得到確定結(jié)果,而設(shè)計(jì)模式不是??丛O(shè)計(jì)模式類的文章的時(shí)候,看到高贊或者高踩,都要看作者對(duì)這個(gè)模式的理解,沒有帶個(gè)人理解的,都是筆記(雖說我也寫了幾篇設(shè)計(jì)模式的筆記),而已。

水平有限,難免有錯(cuò),還請(qǐng)?jiān)u論區(qū)指責(zé)下
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評(píng)論 19 139
  • 沒有人買車會(huì)只買一個(gè)輪胎或者方向盤,大家買的都是一輛包含輪胎、方向盤和發(fā)動(dòng)機(jī)等多個(gè)部件的完整汽車。如何將這些部件組...
    justCode_閱讀 1,995評(píng)論 1 6
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,664評(píng)論 18 399
  • 1 場(chǎng)景問題# 1.1 訂單處理系統(tǒng)## 考慮這樣一個(gè)實(shí)際應(yīng)用:訂單處理系統(tǒng)。 現(xiàn)在有一個(gè)訂單處理的系統(tǒng),里面有個(gè)...
    七寸知架構(gòu)閱讀 4,660評(píng)論 3 63
  • 如何利用碎片化時(shí)間? 第一制定時(shí)間計(jì)劃。對(duì)孩子啟蒙越早越好,此時(shí)此刻開始就行動(dòng)。對(duì)嗯,時(shí)間不夠用的焦慮呀,然后很多...
    童潤(rùn)Mama閱讀 248評(píng)論 0 0

友情鏈接更多精彩內(nèi)容