設計模式之建造者模式

思路多態下,建造不同類型的“建築”,通過第三方監工監製,用戶調用監工即可

場景之一:蓋房子舉例,房子本身有很多個組成部分,各組件息息相關缺一不可,否則房倒屋塌。而其構造過程也是相當複雜的,但大家不必擔心,爲響應我們簡約直觀的一貫宗旨,這裏只將其簡化拆分成地基、牆體、屋頂三部分,首先來看建築物類。

package com.yitian.builder;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description 建築物
 * @Author yitianRen
 * @Date 2019/9/17 10:34
 * @Version 1.0
 **/
public class Building {

    // 用來模擬房子組件的堆疊
    private List<String> buildingComponents = new ArrayList<>();

    public void setBasement(String basement) {// 地基
        this.buildingComponents.add(basement);
    }

    public void setWall(String wall) {// 牆體
        this.buildingComponents.add(wall);
    }

    public void setRoof(String roof) {// 房頂
        this.buildingComponents.add(roof);
    }

    @Override
    public String toString() {
        String buildingStr = "";
        for (int i = buildingComponents.size() - 1; i >= 0; i--) {
            buildingStr += buildingComponents.get(i);
        }
        return buildingStr;
    }
}

爲了模擬建築物通用類中各組件的建造順序,我們在第以List來模擬三個組件的堆疊,之後是它們對應的三個建造方法,最後於的toString方法自下而上的打印出最終完成的房子。看起來是不難,但怎樣從這個類直接構造出一個房子呢?怎樣去設置這些字符串的組件屬性呢?此時客戶端一頭霧水,還是找個專業施工方吧,先定義個施工方接口。

package com.yitian.builder;

/**
 * @Author:yitianRen
 * @Date:10:37 2019/9/17
 * Description:施工者 建造
 */
public interface Builder {

    public void buildBasement();

    public void buildWall();

    public void buildRoof();

    public Building getBuilding();

}

別墅施工者:

package com.yitian.builder;

/**
 * @Description 建造別墅
 * @Author yitianRen
 * @Date 2019/9/17 10:39
 * @Version 1.0
 **/
public class HouseBuilder implements Builder {
    private Building house;

    public HouseBuilder() {
        house = new Building();
    }

    @Override
    public void buildBasement() {
        System.out.println("挖地基,部署管道、線纜,水泥加固,搭建圍牆、花園。");
        house.setBasement("╬╬╬╬╬╬╬╬\n");
    }

    @Override
    public void buildWall() {
        System.out.println("搭建木質框架,石膏板封牆並粉飾內外牆。");
        house.setWall("|田|田 田|\n");
    }

    @Override
    public void buildRoof() {
        System.out.println("建造木質屋頂、閣樓,安裝煙囪,做好防水。");
        house.setRoof("╱◥███◣\n");
    }

    @Override
    public Building getBuilding() {
        return house;
    }

}

公寓施工者:

package com.yitian.builder;

/**
 * @Description 建造八層公寓
 * @Author yitianRen
 * @Date 2019/9/17 10:42
 * @Version 1.0
 **/
public class ApartmentBuilder implements Builder {

    private Building apartment;

    public ApartmentBuilder() {
        apartment = new Building();
    }

    @Override
    public void buildBasement() {
        System.out.println("深挖地基,修建地下車庫,部署管道、線纜、風道。");
        apartment.setBasement("╚═════════╝\n");
    }

    @Override
    public void buildWall() {
        System.out.println("搭建多層建築框架,建造電梯井,鋼筋混凝土澆灌。");
        for (int i = 0; i < 8; i++) {// 此處假設固定8層
            apartment.setWall("║ □ □ □ □ ║\n");
        }
    }

    @Override
    public void buildRoof() {
        System.out.println("封頂,部署通風井,做防水層,保溫層。");
        apartment.setRoof("╔═════════╗\n");
    }

    @Override
    public Building getBuilding() {
        return apartment;
    }

}

這時候建築有了,施工者有了,那麼需要一個監工負責監製:

package com.yitian.builder;

/**
 * @Description 監工
 * @Author yitianRen
 * @Date 2019/9/17 10:51
 * @Version 1.0
 **/
public class Director {

    private Builder builder;

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

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }

    public Building direct() {
        System.out.println("=====工程項目啓動=====");
        // 第一步,打好地基;
        builder.buildBasement();
        // 第二步,建造框架、牆體;
        builder.buildWall();
        // 第三步,封頂;
        builder.buildRoof();
        System.out.println("=====工程項目竣工=====");
        return builder.getBuilding();
    }
}

一切都有了,客戶這下可以方便的請大家爲自己建造房子了,別墅和八層小公寓要建造了!

package com.yitian.builder;

/**
 * @Description 客戶尋求監工監製住房
 * @Author yitianRen
 * @Date 2019/9/17 10:53
 * @Version 1.0
 **/
public class Client {

    public static void main(String[] args) {
        //招工,建別墅。
        Builder builder = new HouseBuilder();
        //交給工程總監
        Director director = new Director(builder);
        System.out.println(director.direct());
        //替換施工方,建公寓。
        director.setBuilder(new ApartmentBuilder());
        System.out.println(director.direct());
        /*
        =====工程項目啓動=====
            挖地基,部署管道、線纜,水泥加固,搭建圍牆、花園。
            搭建木質框架,石膏板封牆並粉飾內外牆。
            建造木質屋頂、閣樓,安裝煙囪,做好防水。
            =====工程項目竣工=====
            ╱◥███◣
            |田|田 田|
            ╬╬╬╬╬╬╬╬

            =====工程項目啓動=====
            深挖地基,修建地下車庫,部署管道、線纜、風道。
            搭建多層建築框架,建造電梯井,鋼筋混凝土澆灌。
            封頂,部署通風井,做防水層,保溫層。
            =====工程項目竣工=====
            ╔═════════╗
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ║ □ □ □ □ ║
            ╚═════════╝
        */
    }

}

項目終於竣工了,對於複雜對象的構建,專業的建造團隊顯然是不可或缺的,尤其是產品內部組件間有某種關聯性,構建的順序性,所以我們把製造工序抽離出來交給了工程總監(Director),而產品各種製造工藝則被多態化交給不同的施工方(Builder)去各顯神通,最終達成以相同的構造過程生產不同產品的展現的目的,工序不可亂,工藝不可缺

文章來源  微信公衆號  java知音  設計模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章