一、builder 簡介
在常見的設(shè)計模式中,“Builder” 通常是指一種設(shè)計模式,而不是具體的類或方法。Builder 模式是一種創(chuàng)建型設(shè)計模式,其目的是通過提供一個獨立的構(gòu)建器類來構(gòu)建一個復(fù)雜對象。
建造者模式(Builder Pattern) 是一種創(chuàng)建型設(shè)計模式,它的主要目標(biāo)是為了將一個復(fù)雜對象的構(gòu)建與其表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
1、主要角色
- 產(chǎn)品(Product):表示被構(gòu)建的復(fù)雜對象。在建造過程完成后,該對象通常包含多個部件。
- 抽象建造者(Builder):聲明了創(chuàng)建產(chǎn)品各個部件的抽象接口。通常包含創(chuàng)建和返回產(chǎn)品的方法。
- 具體建造者(Concrete Builder):實現(xiàn)了抽象建造者接口,負(fù)責(zé)實際構(gòu)建產(chǎn)品的各個部件。具體建造者通常會有一個與產(chǎn)品相關(guān)的成員變量,用于保存當(dāng)前產(chǎn)品的狀態(tài)。
- 指導(dǎo)者(Director):負(fù)責(zé)使用建造者對象構(gòu)建產(chǎn)品。指導(dǎo)者通常不知道具體產(chǎn)品的類型和內(nèi)部結(jié)構(gòu),僅僅負(fù)責(zé)按照一定的構(gòu)建步驟調(diào)用建造者的方法。
在 Java 中,Builder 模式通常由一個包含所有構(gòu)建步驟的內(nèi)部靜態(tài)類(稱為 Builder 類)來實現(xiàn)。這個 Builder 類負(fù)責(zé)設(shè)置對象的各個屬性,最后通過一個 build() 方法來構(gòu)建目標(biāo)對象。
總體而言,Builder 模式是通過一個獨立的構(gòu)建器類來創(chuàng)建對象,使得對象的構(gòu)建過程更加靈活和清晰。
二、builder 用法及實現(xiàn)
1、手寫builder類
一般來說,builder
的用法如下:
-
創(chuàng)建一個靜態(tài)內(nèi)部類作為建造者(Builder):
private String property1; private int property2; // 私有構(gòu)造函數(shù),限制直接實例化 private MyClass() { } // Getter 方法省略... // 靜態(tài)內(nèi)部類作為建造者 public static class Builder { private MyClass instance = new MyClass(); public Builder withProperty1(String value) { instance.property1 = value; return this; } public Builder withProperty2(int value) { instance.property2 = value; return this; } public MyClass build() { return instance; } } // 其他靜態(tài)工廠方法或?qū)嵗椒?.. // 示例:使用 builder() 創(chuàng)建對象 public static Builder builder() { return new Builder(); } }
-
使用建造者設(shè)置屬性:
MyClass myObject = MyClass.builder() .withProperty1("value1") .withProperty2(42) .build();
通過這種方式,你可以在創(chuàng)建對象的時候逐步設(shè)置屬性,而不是通過構(gòu)造函數(shù)傳遞參數(shù)。這樣的設(shè)計使得代碼更加清晰,易于維護(hù),尤其當(dāng)有多個可選屬性時,建造者模式可以提供更好的靈活性。
2、Lombok實現(xiàn)
使用 Lombok 這樣的工具,它提供了 @Builder 注解,該注解可以用于生成 Builder 模式相關(guān)的代碼。下面是一個使用 Lombok 的 @Builder 注解的簡單示例:詳情參考【注解】@Builder、@SuperBuilder Lombok 中的建設(shè)者
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Example {
private final String name;
private final int age;
}
// 在其他類中使用
Example example = Example.builder()
.name("John")
.age(25)
.build();
在這個示例中,Builder
注解幫助生成了一個名為 builder
的靜態(tài)內(nèi)部類,該類用于創(chuàng)建 Example 對象的實例。這種方式使得對象的創(chuàng)建更加清晰和方便。
請注意,@Builder
是 Lombok 提供的功能,如果你沒有使用 Lombok,你需要手動編寫 Builder 模式的代碼。
三、作用和優(yōu)勢
1、工作流程
- 客戶端(Client):創(chuàng)建指導(dǎo)者對象,并指定一個具體的建造者對象。
- 指導(dǎo)者(Director):調(diào)用具體建造者的一系列方法,按照一定的步驟來構(gòu)建產(chǎn)品。
- 具體建造者(Concrete Builder):實現(xiàn)了具體的構(gòu)建步驟,負(fù)責(zé)構(gòu)建產(chǎn)品的各個部件。
- 產(chǎn)品(Product):表示最終構(gòu)建成功的對象。
2、優(yōu)點
- 分離構(gòu)建和表示:建造者模式將對象的構(gòu)建和最終表示分離,使得相同的構(gòu)建過程可以創(chuàng)建不同的表示。
- 更好的控制構(gòu)建過程:通過指導(dǎo)者來控制構(gòu)建過程,可以靈活地配置和改變產(chǎn)品的構(gòu)建流程。
- 更好的復(fù)用性:可以通過不同的具體建造者來創(chuàng)建不同類型的產(chǎn)品,提高了代碼的復(fù)用性。
- 更好的擴(kuò)展性:增加新的具體建造者無需修改指導(dǎo)者的代碼,符合開閉原則。
四、應(yīng)用場景
- 需要創(chuàng)建復(fù)雜對象:當(dāng)對象的構(gòu)建過程較為復(fù)雜,涉及多個部件組合,且這些部件可能存在多種組合方式時,可以考慮使用建造者模式。
- 對象的構(gòu)建步驟順序不固定:如果對象的構(gòu)建步驟的順序不固定,或者某些步驟可以省略,可以通過建造者模式更靈活地構(gòu)建對象。
- 想要避免使用過多的構(gòu)造方法:在類的構(gòu)造方法中,參數(shù)的組合可能有多種情況,如果為每一種情況都提供一個構(gòu)造方法,會導(dǎo)致構(gòu)造方法的數(shù)量急劇增加。建造者模式可以通過一系列的方法來設(shè)置對象的不同部分,避免構(gòu)造方法的爆炸性增長。
- 希望在創(chuàng)建對象時能夠更好地控制對象的構(gòu)建過程:通過使用指導(dǎo)者(Director)來封裝對象的構(gòu)建過程,客戶端只需要指定具體的建造者和調(diào)用指導(dǎo)者的構(gòu)建方法,而無需關(guān)心對象的具體構(gòu)建過程。
- 想要避免在客戶端暴露產(chǎn)品的內(nèi)部表示:建造者模式將產(chǎn)品的構(gòu)建和最終表示分離,客戶端只需要關(guān)心產(chǎn)品的最終狀態(tài)而不需要知道具體的構(gòu)建細(xì)節(jié),從而降低了客戶端與產(chǎn)品的耦合度。
總的來說,建造者模式適用于需要創(chuàng)建復(fù)雜對象,且構(gòu)建過程靈活多變的場景。在這種模式下,將對象的構(gòu)建過程封裝在具體建造者中,通過指導(dǎo)者來統(tǒng)一調(diào)度,使得客戶端可以更方便地構(gòu)建出所需的對象。
五、應(yīng)用實例(電商)
在電商項目中,一個典型的場景是創(chuàng)建訂單(Order)。訂單通常包含多個部分,例如訂單項、收貨地址、支付信息等,而每個部分的構(gòu)建可能涉及到多個步驟和參數(shù)。建造者模式在這種情況下可以很好地應(yīng)用。
讓我們考慮一個簡化的訂單創(chuàng)建過程,使用建造者模式來構(gòu)建訂單對象。假設(shè)訂單包括訂單號、訂單項列表、收貨地址、支付信息等。文章來源:http://www.zghlxwxcb.cn/news/detail-812342.html
1、首先,定義訂單對象:
// 訂單對象
public class Order {
private String orderNumber;
private List<OrderItem> orderItems;
private String shippingAddress;
private String paymentInfo;
// 構(gòu)造方法私有化,通過建造者來構(gòu)建對象
private Order() {
}
// 提供獲取訂單信息的方法
// ...
}
2、然后,定義訂單項對象:
// 訂單項對象
public class OrderItem {
private String productCode;
private int quantity;
// 構(gòu)造方法
public OrderItem(String productCode, int quantity) {
this.productCode = productCode;
this.quantity = quantity;
}
// 提供獲取訂單項信息的方法
// ...
}
3、接下來,定義訂單的建造者(OrderBuilder):
// 訂單建造者
public class OrderBuilder {
private Order order;
public OrderBuilder() {
this.order = new Order();
}
public OrderBuilder setOrderNumber(String orderNumber) {
order.orderNumber = orderNumber;
return this;
}
public OrderBuilder addOrderItem(String productCode, int quantity) {
if (order.orderItems == null) {
order.orderItems = new ArrayList<>();
}
order.orderItems.add(new OrderItem(productCode, quantity));
return this;
}
public OrderBuilder setShippingAddress(String shippingAddress) {
order.shippingAddress = shippingAddress;
return this;
}
public OrderBuilder setPaymentInfo(String paymentInfo) {
order.paymentInfo = paymentInfo;
return this;
}
public Order build() {
return order;
}
}
4、最后,在客戶端中使用建造者模式來構(gòu)建訂單:
public class Main {
public static void main(String[] args) {
// 使用建造者構(gòu)建訂單
Order order = new OrderBuilder()
.setOrderNumber("123456")
.addOrderItem("P001", 2)
.addOrderItem("P002", 1)
.setShippingAddress("123 Main St, City")
.setPaymentInfo("Credit Card")
.build();
// 打印訂單信息
System.out.println("Order Number: " + order.getOrderNumber());
System.out.println("Shipping Address: " + order.getShippingAddress());
System.out.println("Payment Info: " + order.getPaymentInfo());
System.out.println("Order Items: " + order.getOrderItems());
}
}
在這個例子中,通過使用建造者模式,客戶端可以按照自己的需求逐步設(shè)置訂單的各個部分,最后調(diào)用 build() 方法生成訂單對象。這種方式既靈活又可讀性好,而且使得訂單對象的創(chuàng)建過程與客戶端解耦。文章來源地址http://www.zghlxwxcb.cn/news/detail-812342.html
到了這里,關(guān)于【設(shè)計模式】builder 創(chuàng)建者設(shè)計模式詳解(包含電商應(yīng)用場景及代碼示例)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!