Builder模式

本文介绍如何利用Builder模式简化复杂对象的构造过程,避免多参数构造函数带来的问题,提高代码可读性和灵活性。

在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成。那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Builder模式来替代多参数构造函数是一个比较好的实践法则。

我们常常会面临编写一个这样的实现类(假设类名叫DoDoContact),这个类拥有多个构造函数,

DoDoContact(String name);

DoDoContact(String name, int age);

DoDoContact(String name, int age, String address);

DoDoContact(String name, int age, String address, int cardID);

这样一系列的构造函数主要目的就是为了提供更多的客户调用选择,以处理不同的构造请求。这种方法很常见,也很有效力,但是它的缺点也很多。类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作。其次,这样的构造函数灵活性也不高,而且在调用时你不得不提供一些没有意义的参数值,例如,DoDoContact("Ace", -1, "SH"),显然年龄为负数没有意义,但是你又不的不这样做,得以符合Java的规范。如果这样的代码发布后,后面的维护者就会很头痛,因为他根本不知道这个-1是什么含义。对于这样的情况,就非常适合使用Builder模式。Builder模式的要点就是通过一个代理来完成对象的构建过程。这个代理职责就是完成构建的各个步骤,同时它也是易扩展的。下面是改写自Effective Java里面的一段代码:

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
public class DoDoContact {
    private final int    age;
    private final int    safeID;
    private final String name;
    private final String address;
 
    public int getAge() {
        return age;
    }
 
    public int getSafeID() {
        return safeID;
    }
 
    public String getName() {
        return name;
    }
 
    public String getAddress() {
        return address;
    }
 
    public static class Builder {
        private int    age     = 0;
        private int    safeID  = 0;
        private String name    = null;
        private String address = null;
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
32
33
   // 构建的步骤
        public Builder(String name) {
            this.name = name;
        }
 
        public Builder age(int val) {
            age = val;
            return this;
        }
 
        public Builder safeID(int val) {
            safeID = val;
            return this;
        }
 
        public Builder address(String val) {
            address = val;
            return this;
        }
 
        public DoDoContact build() { // 构建,返回一个新对象
            return new DoDoContact(this);
        }
    }
 
    private DoDoContact(Builder b) {
        age = b.age;
        safeID = b.safeID;
        name = b.name;
        address = b.address;
 
    }
}

最终,客户程序可以很灵活的去构建这个对象。

1
2
3
4
DoDoContact ddc = new DoDoContact.Builder("Ace").age(10)
                .address("beijing").build();
System.out.println("name=" + ddc.getName() + "age =" + ddc.getAge()
                + "address" + ddc.getAddress());
### Builder模式的使用与实现 Builder模式是一种用于构建复杂对象的设计模式,其主要目的是通过逐步设置对象的属性来简化对象的创建过程。这种方式不仅提高了代码的可读性,还隐藏了对象创建的复杂性。 在Java中,Builder模式通常通过以下方式实现: 1. **定义一个包含必要参数的构造函数**:Builder类的构造函数接受对象的核心属性作为参数[^2]。 2. **提供链式调用的方法**:每个设置方法返回Builder对象本身,从而允许将多个设置方法链接在一起[^5]。 3. **创建最终对象**:通过`build()`方法返回构建完成的对象实例[^4]。 以下是一个典型的Builder模式实现示例: ```java // 被构建的复杂对象 public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int sodium; private final int carbohydrates; // 私有构造函数,只能通过Builder创建 private NutritionFacts(Builder builder) { this.servingSize = builder.servingSize; this.servings = builder.servings; this.calories = builder.calories; this.sodium = builder.sodium; this.carbohydrates = builder.carbohydrates; } // Getter 方法 public int getServingSize() { return servingSize; } public int getServings() { return servings; } public int getCalories() { return calories; } public int getSodium() { return sodium; } public int getCarbohydrates() { return carbohydrates; } // 静态内部类 Builder public static class Builder { private final int servingSize; private final int servings; private int calories = 0; private int sodium = 0; private int carbohydrates = 0; // 必要参数的构造函数 public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } // 设置可选参数的方法,支持链式调用 public Builder calories(int val) { this.calories = val; return this; } public Builder sodium(int val) { this.sodium = val; return this; } public Builder carbohydrates(int val) { this.carbohydrates = val; return this; } // 构建最终对象 public NutritionFacts build() { return new NutritionFacts(this); } } } // 使用示例 NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8) .calories(100) .sodium(35) .carbohydrates(27) .build(); ``` 上述代码展示了如何通过Builder模式构建一个复杂的`NutritionFacts`对象。通过链式调用,可以清晰地设置对象的各个属性。 ### 注意事项 - **必要参数与可选参数**:Builder模式的一个重要特性是区分必要参数和可选参数。必要参数通常在Builder类的构造函数中指定,而可选参数则通过链式调用设置[^2]。 - **不可变对象**:通过私有构造函数和Builder类,可以确保生成的对象是不可变的,从而提高程序的安全性[^4]。 - **适用场景**:当对象的构造需要多步初始化或赋值时,Builder模式尤为适用[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值