设计模式 - Builder 模式

Effective Java 第2条:遇到多个构造器参数时要考虑使用构建器

三种创建对象的方式。

目录

  • 重叠构造器
  • JavaBeans
  • 构建器 Builder

#重叠构造器

/**
 * Create By IntelliJ IDEA.
 *
 * @Author: Cheng
 * @Date: 2017/10/30
 * @Time: 19:21
 * 

* 层叠构造器 */ public class User { private String name; // required private String password; // required private int id; // optional private String email; // optional private String phone; // optional private String address; // optional public User(String name, String password, int id, String email, String phone, String address) { this.name = name; this.password = password; this.id = id; this.email = email; this.phone = phone; this.address = address; } public User(String name, String password) { this(name, password, -1, null, null, null); } public User(String name, String password, int id) { this(name, password, id, null, null, null); } public User(String name, String password, int id, String email) { this(name, password, id, email, null, null); } public User(String name, String password, int id, String email, String phone) { this(name, password, id, email, phone, null); } // 不提供 setter 方法,该对象就是不可变的了。 }

提供第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依次类推,最后一个构造器包含所有可选参数。

重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且依然较难阅读。

参数一多起来不阅读文档将很难理解创建对象该传什么参数 或者将参数顺序搞乱


#JavaBeans

/**
 * Create By IntelliJ IDEA.
 *
 * @Author: Cheng
 * @Date: 2017/10/30
 * @Time: 19:21
 * 

* JavaBeans */ public class User { private String name; // required private String password; // required private int id; // optional private String email; // optional private String phone; // optional private String address; // optional public User(String name, String password) { this.name = name; this.password = password; } // 省略getter and setter方法。 }

JavaBeans模式弥补了重叠构造器的不足。说的明白点,就是创建实例很容易,这样产生的代码读起来也很容易 get set

但是JavaBeans模式有一个缺点。因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态,也就是说,JavaBean是非线程安全的。

JavaBeans模式阻止了把类做成不可变的可能。set


#构建器 Builder

/**
 * Create By IntelliJ IDEA.
 *
 * @Author: Cheng
 * @Date: 2017/10/30
 * @Time: 18:34
 * 

* 构建器模式 */ /** * 用户类 * * 帐号和密码必须输入 * id不赋值表示未存入数据库 * 邮箱、手机、地址为选填项 */ public class User { private String name; // required private String password; // required private int id; // optional private String email; // optional private String phone; // optional private String address; // optional /** * 构造方法传入构造器 * @param builder */ private User(Builder builder) { this.id = builder.id; this.name = builder.name; this.password = builder.password; this.email = builder.email; this.phone = builder.phone; this.address = builder.address; } /** * User类的构造器 * 选填属性设置默认值 * * 必须传入的属性由构造器传入设置 * 选填属性由方法设置 */ public static class Builder { private String name; private String password; private int id = -1; private String email = "未设置"; private String phone = "未设置"; private String address = "未设置"; public Builder(String name, String password) { this.name = name; this.password = password; } /** * 返回的是建造器对象 * @param email * @return */ public Builder setEmail(String email) { this.email = email; return this; } public Builder setPhone(String phone) { this.phone = phone; return this; } public Builder setAddress(String address) { this.address = address; return this; } public User build() { return new User(this); } } // 不提供 setter 方法,该对象就是不可变的了。也就是说,保证了同步性。 }

拥有重叠构造器模式的安全性,也能保证JavaBean模式那么好的代码可读性。这就是 Builder 模式的一种形式。

不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器,得到一个
builder 对象。然后客户端在 builder 对象上调用类似 setter 的方法来设置可选参数。最后调用无参的 build 方法来生成不可变的对象。

这个 builder 是它构建的类的静态成员类。

注意 User 被设计成不可变的了,所有的默认参数值都单独放在一个地方。builder 的 setter 方法返回 builder 本身,以便把调用链接起来。下面是客户端代码:

public static void main(String[] args) {
        User user = new User.Builder("cheng", "********")
                .setEmail("qq.com")
                .setPhone("110")
                .setAddress("HangZhou")
                .build();

        System.out.println(user);
}

builder 就像个构造器一样,可以对器参数强加约束条件。buld 方法可以检验这些约束条件。

public User build() {
        // 校验逻辑
        return new User(this);
}

不足

  1. 比起另外两种创建模式,Builder 模式多创建了一个构建器对象。
  2. 代码量比重叠构造器模式更加冗长。

#总结

如果类的构造器中具有多个参数,并且对安全有要求,设置这种类时,Builder 模式就是种不错的选择。

你可能感兴趣的:(设计模式 - Builder 模式)