Builder(建造者模式)

目錄

design pattern 以java 為例

特點

將一個複雜對象的構建過程封裝起來,使得同樣的構建過程可以創造不同的表示,簡單講就是

把複雜的都包成api

舉例

反例

Person 裡面包括多個屬性,但如果其中有幾個參數是非必填,則

  • 缺乏彈性:如果Person的某些屬性是可選的,使用這種重載構造函數的方式會導致必須創建多個構造函數來支持不同的參數組合。
  • 可讀性差:隨著參數數量的增加,調用這些重載構造函數的代碼變得難以理解,特別是當多個參數具有相同的類型時。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Person {
    private String name;
    private int age;
    private String phoneNumber;
    private String address;

    public Person(String name, int age, String phoneNumber, String address) {
    this.name = name;
    this.age = age;
    this.phoneNumber = phoneNumber;
    this.address = address;
    }

    // Getters and setters
    }

修正

定義builder

person的constructor封在 PersonBuilder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class PersonBuilder {
private String name;
private int age;
private String phoneNumber;
private String address;

public PersonBuilder setName(String name) {
this.name = name;
return this;
}

public PersonBuilder setAge(int age) {
this.age = age;
return this;
}

public PersonBuilder setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}

public PersonBuilder setAddress(String address) {
this.address = address;
return this;
}

public Person build() {
return new Person(name, age, phoneNumber, address);
}
}

修改person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person {
private String name;
private int age;
private String phoneNumber;
private String address;

private Person(String name, int age, String phoneNumber, String address) {
this.name = name;
this.age = age;
this.phoneNumber = phoneNumber;
this.address = address;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", phoneNumber='" + phoneNumber + '\'' +
", address='" + address + '\'' +
'}';
}

public static PersonBuilder builder() {
return new PersonBuilder();
}
}

使用Builder模式創建Person

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String[] args) {
Person person = Person.builder()
.setName("John Doe")
.setAge(30)
.setPhoneNumber("123456789")
.setAddress("123 Main St")
.build();

System.out.println(person.toString());
}
}
1
Person{name='John Doe', age=30, phoneNumber='123456789', address='123 Main St'} 

優點

1. 提高可讀性

當創建擁有多個屬性的對象時,直接使用包含多個參數的構造函數會讓代碼難以閱讀和理解。建造者模式通過命名方法(即setter方法)逐一設置屬性,使得代碼的可讀性大大提高,一目了然地顯示了正在設置的屬性及其值。

2. 簡化對象的創建

對於具有多個構造參數的類,特別是當某些參數可選時,如果使用重載構造函數來實現,會導致構造函數的爆炸性增長。建造者模式允許用戶只設置對他們有意義的參數,並且可以在單一位置進行設置,避免了重載構造函數或多個setter調用的混亂。

3. 促進不可變性

對於需要創建不可變對象的情況,建造者模式非常有用。一旦通過建造者配置了對象的所有必要屬性,就可以創建一個不可變的對象實例,而無需對對象實例進行進一步修改。這有助於保證線程安全性和對象的一致性。

4. 支持鏈式調用

建造者模式支持鏈式調用,這使得代碼更加簡潔,也更易於編寫和理解。鏈式調用提供了一種流暢的接口,讓客戶端代碼在一行或少數幾行內完成複雜對象的構建。

5. 分離複雜構建過程和表示

建造者模式將對象的構建過程與其表示分離,使得相同的構建過程可以創建不同的表示。這對於創建具有多種表示形式的對象特別有用,如文本、XML、JSON等不同格式的對象序列化。

6. 靈活性和擴展性

建造者模式使得新增或更改對象的屬性變得更加容易,只需修改建造者本身而不影響到創建對象的客戶端代碼。這為擴展和維護提供了極大的方便。


Builder(建造者模式)
https://shengshengyang.github.io/2024/04/03/builder/
作者
Dean Yang
發布於
2024年4月3日
許可協議