1. 程式人生 > >設計模式-建造者模式(Builder)

設計模式-建造者模式(Builder)

建造者模式(Builder)

  • 定義 : 將一個複雜物件的構建與它的表示分離, 是的同樣的構建過程可以建立不同的表示
  • 使用者只需指定需要建造的型別就可以得到它們, 建造過程及細節不需要知道
  • 型別 : 建立型設計模式

適用場景

  • 一個物件有非常複雜的內部結構
  • 想把複雜物件的建立和使用分離

優點

  • 封裝性好, 建立和使用分離
  • 擴充套件性好, 建造類之間獨立, 一定程度上解耦

缺點

  • 產生多餘的Builder物件
  • 產品內部發生變化, 建造者都要修改, 成本較大

模式角色

  • Builder : 為建立一個Product物件的各個部件指定抽象介面

  • ConcreteBuilder : Builder的實現類

    • 實現Builder的介面以構造和裝配該產品的各個部件
    • 定義並明確它所建立的表示
    • 提供一個檢索產品的介面
  • Director : 構造一個使用Builder介面的物件

  • Product : 被構造的物件

    • 表示被構造的複雜物件。ConcreteBuilder 建立該產品的內部表示並定義它的裝配過程
    • 包含定義組成部件的類,包括將這些部件裝配成最終產品的介面

程式碼演示

場景: 組裝一臺電腦, 場景中各個類對應的角色如下 :

  • Person,組裝電腦的人, 對應Director
  • ComputerBuilder, 對應ConcreteBuilder
  • IComputerBuilder介面, 對應模式中的Builder
  • Computer, 對應Product

版本一

UML類圖

在這裡插入圖片描述

IComputerBuilder構造者介面, 對應模式中Builder

/**
 * Builder介面
 * 可以使用介面或者抽象類
 * @author 七夜雪
 * @create 2018-11-22 16:53
 */
public interface IComputerBuilder { public void buildCpu(String cpu); public void buildMemory(String memory); public void buildMainboard(String mainboard); public void buildDisk(String disk); public Computer build(); }

ComputerBuilder構造者實現, 對應模式中ConcreteBuilder角色

/**
 * builder模式中的builder
 * @author 七夜雪
 * 2018/11/14 13:51
 */
public class ComputerBuilder implements IComputerBuilder{
    private Computer computer  = new Computer();


    @Override
    public Computer build() {
        return this.computer;
    }

    @Override
    public void buildCpu(String cpu){
        computer.setCpu(cpu);
    }

    @Override
    public void buildMemory(String memory){
        computer.setMemory(memory);
    }

    @Override
    public void buildMainboard(String mainboard){
        computer.setMainboard(mainboard);
    }

    @Override
    public void buildDisk(String disk){
        computer.setDisk(disk);
    }

}

Computer電腦類, 對應模式中Product角色

/**
 * 電腦類,Builder模式中的Product
 *
 * @author 七夜雪
 * 2018/11/14 13:48
 */
public class Computer {

    private String cpu;
    private String memory;
    private String mainboard;
    private String disk;

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

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

    public void setMainboard(String mainboard) {
        this.mainboard = mainboard;
    }

    public void setDisk(String disk) {
        this.disk = disk;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                ", disk='" + disk + '\'' +
                '}';
    }
}

Person類, 對應模式中的Director角色

/**
 * builder模式中的Director
 * @author 七夜雪
 * 2018/11/14 15:23
 */
public class Person {
    private ComputerBuilder builder;

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

    public Computer excuteBuilder(String cpu, String memory, String disk, String mainboard){
        builder.buildCpu(cpu);
        builder.buildMemory(memory);
        builder.buildDisk(disk);
        builder.buildMainboard(mainboard);
        return builder.build();
    }

}

測試類, 對應模式中的Client角色

/**
 * builder模式測試類
 * @author 七夜雪
 * 2018/11/14 13:56
 */
public class Client {

    public static void main(String[] args) {
        ComputerBuilder builder = new ComputerBuilder();
        Person director = new Person(builder);
        Computer computer = director.excuteBuilder("酷睿I7", "金士頓 DDR4 16G", "三星512G SSD", "華碩X99");
        System.out.println(computer);
    }

}

版本二

版本一種, 如果product存在很多屬性, 在執行director的excuteBuilder方法時要傳入很多引數, 容易出現錯誤, 而且如果有些屬性不需要的話, 也必須要傳一個預設值, 所以更通用的一種寫法, 就是講Product和Builder寫在一起, Builder作為Product類的內部類, 同時採用鏈式程式設計方式, 可以選擇構造部分屬性, 對於不需要的屬性則不需要進行構造

UML 類圖

在這裡插入圖片描述

程式碼如下:

/**
 * 電腦類,Builder模式中的Product
 *
 * @author 七夜雪
 * 2018/11/14 13:48
 */
public class Computer {

    public Computer(ComputerBuilder computerBuilder) {
        this.cpu = computerBuilder.cpu;
        this.memory = computerBuilder.memory;
        this.mainboard = computerBuilder.mainboard;
        this.disk = computerBuilder.disk;
    }

    private String cpu;
    private String memory;
    private String mainboard;
    private String disk;

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

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

    public void setMainboard(String mainboard) {
        this.mainboard = mainboard;
    }

    public void setDisk(String disk) {
        this.disk = disk;
    }

    public static class ComputerBuilder {
        private String cpu;
        private String memory;
        private String mainboard;
        private String disk;

        public ComputerBuilder buildCPU(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public ComputerBuilder buildMemory(String memory){
            this.memory = memory;
            return this;
        }

        public ComputerBuilder buildMainboard(String mainboard){
            this.mainboard = mainboard;
            return this;
        }

        public ComputerBuilder buildDisk(String disk){
            this.disk = disk;
            return this;
        }

        public Computer build(){
            return new Computer(this);
        }
    }


    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                ", disk='" + disk + '\'' +
                '}';
    }
}
/**
 * Builder第二版測試類
 *
 * @author 七夜雪
 * @create 2018-11-22 17:17
 */
public class ClientV2 {

    public static void main(String[] args) {
        Computer.ComputerBuilder builder = new Computer.ComputerBuilder();
        Computer computer = builder.buildCPU("酷睿I9-9900K")
                .buildMemory("海盜船 DDR4 64G")
                .buildMainboard("華碩Z390")
                .buildDisk("金士頓 1T SSD").build();
        System.out.println(computer);
    }

}

本文參考:
慕課網<java設計模式精講 Debug 方式+記憶體分析>課程
四人幫<設計模式>