1. 程式人生 > 資訊 >加州計劃 2030 年銷售 61% 的電動汽車,環保組織:不行,提高到 80%

加州計劃 2030 年銷售 61% 的電動汽車,環保組織:不行,提高到 80%

在有些情況下,一個物件會有一些重要的性質,在他們沒有被賦值之前,物件不能作為一個完整的產品使用。比如,一個電子郵件有發件人地址、收件人地址、主題、內容、附件等,最起碼在收件人地址沒有賦值之前,這個電子郵件是不能發出的。

在有些情況下,一個物件的一些性質必須按照某個順序賦值才有意義,在某個性質沒有賦值之前,另一個性質則無法賦值。比如,建造房子,一定是要先打地基,然後砌牆,最後封頂。

傳統方式:

這裡我們以建造房屋為例來做說明。首先看傳統方式的建造房屋的方式:

抽象類:

package com.charon.builder;

/**
 * @className: AbstractHouse
 * @description: 抽象類
 * @author: charon
 * @create: 2022-03-13 16:54
 */
public abstract class AbstractHouse {

    /**
     * 打地基
     */
    public abstract void buildBasic();

    /**
     * 砌牆
     */
    public abstract void buildWalls();

    /**
     * 封頂
     */
    public abstract void roofed();

    /**
     * 建造房屋的方法
     */
    public void build(){
        buildBasic();
        buildWalls();
        roofed();
    }
}

實現類:

package com.charon.builder;

/**
 * @className: CommonHouse
 * @description: 普通房子建造類
 * @author: charon
 * @create: 2022-03-13 16:57
 */
public class CommonHouse extends AbstractHouse {
    @Override
    public void buildBasic() {
        System.out.println("普通房子打地基。。。。。");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子砌牆。。。。。");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子封頂。。。。。");
    }
}

測試:

package com.charon.builder;

/**
 * @className: Client
 * @description:
 * @author: charon
 * @create: 2022-03-13 17:01
 */
public class Client {
    public static void main(String[] args) {
        CommonHouse commonHouse = new CommonHouse();
        commonHouse.build();
    }
}

傳統方式的優點是比較好理解,簡單易操作。但缺點是設計的程式結構過於簡單,沒有設計快取層物件,程式的擴充套件和維護不好,也就是說,這種設計方案,把產品(即:房子)和建立產品的過程(即:建房子流程)封裝在一起,耦合性增強。

建造模式:

建造者模式也叫生成器模式,可以將一個產品的內部表象與產品的生成過程分割開來,從而可以是一個建造過程生成具有不同的內部表象的產品物件。建造者模式是一步一步建立一個複雜的物件,他允許使用者只通過指定複雜物件的型別和內容就可以構建他們,使用者不需要知道內部的具體構建細節。

建造模式的UML類圖:

建造者模式主要涉及到抽象建造者、具體建造者、產品、指揮者以下四種角色:

  • 抽象建造者:給出一個抽象介面,以規範產品物件的各個組成成分的建造。通常以抽象類或介面的形式出現。
  • 具體建造者:擔任這個角色的是與應用程式緊密相關的一些類,他們在應用程式呼叫下建立產品的例項。主要由兩個任務:1)實現抽象建造者所宣告的介面,給出一步一步地完成建立產品例項地操作。2).在建造過程完成後,提供產品的例項
  • 產品角色:產品是建造中的複雜物件,一般來說,一個系統中會有對於一個的產品類,而且這些產品類並不一定有共同的介面。
  • 指揮者:擔任這個角色的類呼叫具體建造者角色以建立產品物件,應當指出的是,指揮者角色並沒有產品類的具體只是,真正擁有產品類的具體知識的是具體建造者角色。他的作用主要有兩點:1).隔離了客戶與物件的生產過程,2).負責控制產品物件的生產過程。

抽象建造者:

package com.charon.builder.improve;

/**
 * @className: HouseBuilder
 * @description: 抽象的建造者
 * @author: charon
 * @create: 2022-03-13 19:15
 */
public abstract class HouseBuilder {

    private House house = new House();

    /**
     * 打地基
     */
    public abstract void buildBasic();

    /**
     * 砌牆
     */
    public abstract void buildWalls();

    /**
     * 封頂
     */
    public abstract void roofed();

    /**
     * 建造方法,將產品返回
     * @return
     */
    public House buildHouse(){
        return house;
    }
}

具體建立者:

package com.charon.builder.improve;

/**
 * @className: CommonHouse
 * @description:
 * @author: charon
 * @create: 2022-03-13 19:13
 */
public class CommonHouse extends HouseBuilder {
    @Override
    public void buildBasic() {
        System.out.println("普通房子打地基。。。。。");
    }

    @Override
    public void buildWalls() {
        System.out.println("普通房子砌牆。。。。。");
    }

    @Override
    public void roofed() {
        System.out.println("普通房子封頂。。。。。");
    }
}


package com.charon.builder.improve;

/**
 * @className: HighBuilding
 * @description: 高樓
 * @author: charon
 * @create: 2022-03-13 19:18
 */
public class HighBuilding extends HouseBuilder{

    @Override
    public void buildBasic() {
        System.out.println("高樓 打地基。。。。。");
    }

    @Override
    public void buildWalls() {
        System.out.println("高樓 砌牆。。。。。");
    }

    @Override
    public void roofed() {
        System.out.println("高樓 封頂。。。。。");
    }
}

產品角色:

package com.charon.builder.improve;

/**
 * @className: House
 * @description: 產品角色
 * @author: charon
 * @create: 2022-03-13 19:14
 */
public class House {

    /**
     * 地基
     */
    private String basic;

    /**
     * 牆
     */
    private String walls;

    /**
     * 封頂
     */
    private String roofed;

    /**
     * Gets the value of basic
     *
     * @return the value of basic
     */
    public String getBasic() {
        return basic;
    }

    /**
     * Sets the basic
     *
     * @param basic basic
     */
    public void setBasic(String basic) {
        this.basic = basic;
    }

    /**
     * Gets the value of walls
     *
     * @return the value of walls
     */
    public String getWalls() {
        return walls;
    }

    /**
     * Sets the walls
     *
     * @param walls walls
     */
    public void setWalls(String walls) {
        this.walls = walls;
    }

    /**
     * Gets the value of roofed
     *
     * @return the value of roofed
     */
    public String getRoofed() {
        return roofed;
    }

    /**
     * Sets the roofed
     *
     * @param roofed roofed
     */
    public void setRoofed(String roofed) {
        this.roofed = roofed;
    }
}

指揮者:

package com.charon.builder.improve;

/**
 * @className: HouseDirector
 * @description: 指揮者
 * @author: charon
 * @create: 2022-03-13 19:20
 */
public class HouseDirector {

    HouseBuilder houseBuilder = null;

    public HouseDirector(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    /**
     * Sets the houseBuilder
     *
     * @param houseBuilder houseBuilder
     */
    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    /**
     * 將建造房子的流程交給指揮者
     * @return
     */
    public House constructHouse(){
        houseBuilder.buildBasic();
        houseBuilder.buildWalls();
        houseBuilder.roofed();
        return houseBuilder.buildHouse();
    }
}

測試:

package com.charon.builder.improve;

/**
 * @className: Client
 * @description:
 * @author: charon
 * @create: 2022-03-13 19:19
 */
public class Client {
    public static void main(String[] args) {
        // 蓋普通房子
        CommonHouse commonHouse = new CommonHouse();
        // 準備建立房子的指揮者
        HouseDirector houseDirector = new HouseDirector(commonHouse);
        // 完成蓋房子
        houseDirector.constructHouse();


        // 蓋高樓
        houseDirector.setHouseBuilder(new HighBuilding());
        // 完成蓋房子
        houseDirector.constructHouse();
    }
}

列印:
    普通房子打地基。。。。。
    普通房子砌牆。。。。。
    普通房子封頂。。。。。
    高樓 打地基。。。。。
    高樓 砌牆。。。。。
    高樓 封頂。。。。。

注意事項和細節:

  1. 客戶端不必知道產品內部組成的細節,將產品本身與產品的建立過程解耦,是的相同的建立過程可以建立不同的產品物件
  2. 每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便的替換具體建造者或增加新的具體建造者,使用者使用不的具體建造者即可得到不同的產品物件
  3. 可以更加精細地控制產品地建立過程,將複雜產品地建立步驟分解在不同的方法中,使得創新過程更加清晰,也更方便使用程式來控制建立過程
  4. 增加新的具體建造者無需修改原有類庫的程式碼,指揮者類針對抽象建造者類程式設計,系統擴充套件方便,符合“開-閉”原則
  5. 建造者模式所建立的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因為其使用範圍收到一定的限制
  6. 如果產品的內部變化負責,可能會導致需要定義很多具體建立者類來實現這種變化,導致系統變得很龐大,因此在這種情況下,要考慮是否選擇建立者模式

抽象工廠模式與建立者模式的不同:

抽象工廠模式實現對產品家族的建立,一個產品家族是一系列產品,具有不同分類維度的產品組合,採用抽象工廠模式不需要關心構建過程,只關心什麼產品由什麼工廠生產即可。而建造者模式則是要求按照指定的藍圖建立產品,他的主要目的是通過組裝零配件而生成一個新的產品。