建造者模式(Builder Pattern)是一種創建型設計模式,它將一個復雜對象的構建與表示分離,使得同樣的構建過程可以創建不同的表示。這種模式允許你分步驟構建一個復雜對象,并且可以在構建過程中進行不同的配置。
模式的核心組件
建造者模式通常包含以下四個核心組件:
- 產品(Product):要構建的復雜對象。
- 抽象建造者(Builder):定義了構建產品各個部分的抽象接口。
- 具體建造者(Concrete Builder):實現抽象建造者接口,完成產品各部分的具體構建。
- 指揮者(Director):負責安排復雜對象的構建順序,并使用建造者對象構建產品。
簡單實現
讓我們通過一個示例來詳細說明建造者模式的實現。假設我們要構建一個電腦(Computer)對象,它包含 CPU、內存、硬盤和顯卡等組件。
首先,定義產品類:
// 產品類:電腦
public class Computer {private String cpu;private String memory;private String hardDisk;private String graphicsCard;// 私有構造函數,只能通過Builder創建Computerprivate Computer(Builder builder) {this.cpu = builder.cpu;this.memory = builder.memory;this.hardDisk = builder.hardDisk;this.graphicsCard = builder.graphicsCard;}// Getter方法public String getCpu() {return cpu;}public String getMemory() {return memory;}public String getHardDisk() {return hardDisk;}public String getGraphicsCard() {return graphicsCard;}@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", memory='" + memory + '\'' +", hardDisk='" + hardDisk + '\'' +", graphicsCard='" + graphicsCard + '\'' +'}';}// 靜態內部類:Builderpublic static class Builder {private String cpu;private String memory;private String hardDisk;private String graphicsCard;// 設置CPU,返回Builder實例以便鏈式調用public Builder setCpu(String cpu) {this.cpu = cpu;return this;}// 設置內存,返回Builder實例以便鏈式調用public Builder setMemory(String memory) {this.memory = memory;return this;}// 設置硬盤,返回Builder實例以便鏈式調用public Builder setHardDisk(String hardDisk) {this.hardDisk = hardDisk;return this;}// 設置顯卡,返回Builder實例以便鏈式調用public Builder setGraphicsCard(String graphicsCard) {this.graphicsCard = graphicsCard;return this;}// 構建Computer對象public Computer build() {// 可以在這里添加參數驗證邏輯if (cpu == null || memory == null || hardDisk == null) {throw new IllegalArgumentException("CPU、內存和硬盤是必需的");}return new Computer(this);}}
}
然后,使用建造者模式創建電腦對象:
public class BuilderPatternExample {public static void main(String[] args) {// 使用Builder創建電腦對象Computer gamingComputer = new Computer.Builder().setCpu("Intel i9-12900K").setMemory("32GB DDR5").setHardDisk("2TB NVMe SSD").setGraphicsCard("NVIDIA RTX 3080").build();Computer officeComputer = new Computer.Builder().setCpu("Intel i5-12400").setMemory("16GB DDR4").setHardDisk("512GB SSD").build(); // 辦公電腦可以不設置獨立顯卡System.out.println("游戲電腦配置:" + gamingComputer);System.out.println("辦公電腦配置:" + officeComputer);}
}
如上是一個建造者模式的簡單實現,是不是感覺超級簡單,下面是經典的實現方式
?經典實現
// 1. 產品類:電腦
public class Computer {private String cpu;private String memory;private String hardDisk;private String graphicsCard;// 構造函數和Getter方法public Computer(String cpu, String memory, String hardDisk, String graphicsCard) {this.cpu = cpu;this.memory = memory;this.hardDisk = hardDisk;this.graphicsCard = graphicsCard;}@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", memory='" + memory + '\'' +", hardDisk='" + hardDisk + '\'' +", graphicsCard='" + graphicsCard + '\'' +'}';}
}// 2. 抽象建造者接口
public interface ComputerBuilder {void buildCPU();void buildMemory();void buildHardDisk();void buildGraphicsCard();Computer getComputer();
}// 3. 具體建造者:游戲電腦建造者
public class GamingComputerBuilder implements ComputerBuilder {private Computer computer;public GamingComputerBuilder() {this.computer = new Computer(null, null, null, null);}@Overridepublic void buildCPU() {computer.setCpu("Intel i9-12900K");}@Overridepublic void buildMemory() {computer.setMemory("32GB DDR5");}@Overridepublic void buildHardDisk() {computer.setHardDisk("2TB NVMe SSD");}@Overridepublic void buildGraphicsCard() {computer.setGraphicsCard("NVIDIA RTX 3080");}@Overridepublic Computer getComputer() {return computer;}
}// 3. 具體建造者:辦公電腦建造者
public class OfficeComputerBuilder implements ComputerBuilder {private Computer computer;public OfficeComputerBuilder() {this.computer = new Computer(null, null, null, null);}@Overridepublic void buildCPU() {computer.setCpu("Intel i5-12400");}@Overridepublic void buildMemory() {computer.setMemory("16GB DDR4");}@Overridepublic void buildHardDisk() {computer.setHardDisk("512GB SSD");}@Overridepublic void buildGraphicsCard() {// 辦公電腦可以不設置獨立顯卡}@Overridepublic Computer getComputer() {return computer;}
}// 4. 指揮者:控制構建過程
public class ComputerDirector {private ComputerBuilder builder;public ComputerDirector(ComputerBuilder builder) {this.builder = builder;}public void constructComputer() {builder.buildCPU();builder.buildMemory();builder.buildHardDisk();builder.buildGraphicsCard();}public Computer getComputer() {return builder.getComputer();}
}// 客戶端代碼
public class Client {public static void main(String[] args) {// 構建游戲電腦ComputerBuilder gamingBuilder = new GamingComputerBuilder();ComputerDirector director = new ComputerDirector(gamingBuilder);director.constructComputer();Computer gamingComputer = director.getComputer();// 構建辦公電腦ComputerBuilder officeBuilder = new OfficeComputerBuilder();director = new ComputerDirector(officeBuilder);director.constructComputer();Computer officeComputer = director.getComputer();System.out.println("游戲電腦配置:" + gamingComputer);System.out.println("辦公電腦配置:" + officeComputer);}
}
模式的優點
- 分離構建和表示:使得構建算法可以獨立于產品的表示,提高了系統的可擴展性。
- 分步構建:可以分步驟構建一個復雜對象,允許在構建過程中進行不同的配置。
- 鏈式調用:通過鏈式調用方法設置屬性,使代碼更簡潔易讀。
- 參數驗證:可以在
build()
方法中添加參數驗證邏輯,確保對象的完整性。
模式的應用場景
- 復雜對象構建:當創建一個對象需要很多步驟,并且這些步驟的順序可能不同。
- 可選參數較多:當一個類的構造函數有很多參數,特別是其中很多是可選參數時。
- 構建不同表示:當需要創建同一個產品的不同表示時。
與其他模式的比較
- 工廠模式:工廠模式關注的是整體對象的創建,而建造者模式關注的是對象的分步構建。
- 抽象工廠模式:抽象工廠模式返回的是一系列相關產品,而建造者模式返回的是一個完整的產品。
建造者模式在實際開發中非常常用,特別是在創建復雜對象時。它能夠使代碼更加清晰、靈活,并且易于維護。另外Lombok 的@Builder
注解是一個強大的工具,它能自動生成流式 API 風格的 "建造者模式 (Builder Pattern)" 代碼,從而避免編寫大量樣板代碼。使用該注解可以讓代碼更簡潔,同時保持建造者模式的優勢。