《戰錘40K暗潮》靈能者天賦講解與武器搭配推薦
將一個複雜物件的構建與表示分離,使得同樣的構建過程可以建立不同的表示。
-
分離了部件的構造(由Builder來負責)和裝配(由Director負責)。 從而可以構造出複雜的物件。這個模式適用於:某個物件的構建過程複雜的情況。
-
由於實現了構建和裝配的解耦。不同的構建器,相同的裝配,也可以做出不同的物件;相同的構建器,不同的裝配順序也可以做出不同的物件。也就是
-
建造者模式可以將部件和其組裝過程分開,一步一步建立一個複雜的物件。使用者只需要指定複雜物件的型別就可以得到該物件,而無須知道其內部的具體構造細節。
結構
-
抽象建造者(Builder): 這個介面
-
具體建造者(ConcreteBuilder): 實現Builder介面, 完成複雜產品的各個部件的具體建立方式, 在構造過程完成後, 提供產品的例項
-
產品類(Product): 要建立複雜的物件
-
指揮者類(Director): 呼叫具體建造者來建立複雜物件的各個部分, 在指揮者中不涉及具體產品資訊, 只負責保證物件各個部分完整建立或按照某種順序建立
例項
建立共享單車
生產自行車是一個複雜的過程,它包含了車架,車座等元件的生產。而車架又有碳纖維,鋁合金等材質的,車座有橡膠,真皮等材質。對於自行車的生產就可以使用建造者模式。
這裡Bike是產品,包含車架,車座等元件;Builder是抽象建造者,MobikeBuilder和OfoBuilder是具體的建造者;Director是指揮者。
//自行車類
public class Bike {
private String frame;
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
// 抽象 builder 類
public abstract class Builder {
protected Bike mBike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
}
//摩拜單車Builder類
public class MobikeBuilder extends Builder {
@Override
public void buildFrame() {
mBike.setFrame("鋁合金車架");
}
@Override
public void buildSeat() {
mBike.setSeat("真皮車座");
}
@Override
public Bike createBike() {
return mBike;
}
}
//ofo單車Builder類
public class OfoBuilder extends Builder {
@Override
public void buildFrame() {
mBike.setFrame("碳纖維車架");
}
@Override
public void buildSeat() {
mBike.setSeat("橡膠車座");
}
@Override
public Bike createBike() {
return mBike;
}
}
//指揮者類
public class Director {
private Builder mBuilder;
public Director(Builder builder) {
mBuilder = builder;
}
public Bike construct() {
mBuilder.buildFrame();
mBuilder.buildSeat();
return mBuilder.createBike();
}
}
//測試類
public class Client {
public static void main(String[] args) {
showBike(new OfoBuilder());
showBike(new MobikeBuilder());
}
private static void showBike(Builder builder) {
Director director = new Director(builder);
Bike bike = director.construct();
System.out.println(bike.getFrame());
System.out.println(bike.getSeat());
}
}
注意:
上面示例是 Builder模式的常規用法,指揮者類 Director 在建造者模式中具有很重要的作用,它用於指導具體構建者如何構建產品,控制呼叫先後次序,並向呼叫者返回完整的產品類,但是有些情況下需要簡化系統結構,可以把指揮者類和抽象建造者進行結合
// 抽象 builder 類
public abstract class Builder {
protected Bike mBike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
public Bike construct() {
this.buildFrame();
this.BuildSeat();
return this.createBike();
}
}
說明:
這樣做確實簡化了系統結構,但同時也加重了抽象建造者類的職責,也不是太符合單一職責原則,如果construct() 過於複雜,建議還是封裝到 Director 中。
優缺點
優點
-
封裝性很好, 可以有效的封裝變化, 在使用建造者模式的場景中, 一般產品類和建造者類是比較穩定的, 因此, 將主要的業務邏輯封裝在指揮者類中對整體而言可以取得比較好的穩定性
-
在建造者模式中, 客戶端不必知道產品內部組成的細節, 將產品本身與產品的建立過程解耦, 使得相同的建立過程可以建立不同的產品物件
-
可以更加精細地控制產品的建立過程, 將複雜產品的建立步驟分解在不同的方法中, 使得建立過程更加清晰, 也更方便使用程式來控制建立過程
缺點
所建立的產品一般具有較多的共同點, 其組成部分相似, 如果產品間的差異很大, 則不適合使用建造者模式, 因此其適用範圍收到一定限制
適用場景
建立的是複雜物件, 其產品的各個部分經常綿連者劇烈的變化, 但將他們組合在一起的演算法卻相對穩定, 所以它通常在以下場合下使用
-
建立的物件比較複雜, 由多個部件構成, 各部件面臨著複雜的變化, 但構件間的建造順序是穩定的
-
建立複雜物件的演算法獨立於該物件的組成部分以及他們的裝配方式, 即產品的構建過程和最終的表示(物件)是獨立的
!重要 : 模式擴充套件
建造者模式除了上面的用途外, 在開發中還有一個常用的使用方式, 就是當一個類構造器需要傳入很多引數時, 如果建立這個類的例項, 程式碼可讀性會非常差, 而且容易引入錯誤, 此時就可以利用建造者模式進行重構
package com.itheima.pattern.builder.demo2;
/**
* @author whf
* @version 1.0.0
* @Date: 2022/12/7 17:18
*/
public class Phone {
private String cpu;
private String screen;
private String memory;
private String mainboard;
/**
* 私有構造方法
*
* @param builder
*/
private Phone(Builder builder) {
this.cpu = builder.cpu;
this.screen = builder.screen;
this.memory = builder.memory;
this.memory = builder.memory;
}
/**
* kc 內部類builder
*/
public static final class Builder {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder screen(String screen) {
this.screen = screen;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Builder mainboard(String mainboard) {
this.mainboard = mainboard;
return this;
}
/**
* 使用構建者建立手機物件
*
* @return
*/
public Phone build() {
return new Phone(this);
}
}
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
'}';
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone.Builder()
.cpu("intel")
.screen("huawei")
.mainboard("華碩")
.memory("DDR4")
.build();
System.out.println(phone);
}
}