概述
The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
使用场景
当一个类的构造参数个数超过了4个,而且这些参数有些是可选的参数,考虑使用构造者模式;
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;
当构造过程中允许被构造的对象有不同的表示时。
Builder设计模式中涉及到的参与者
Builder
为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder
实现 Builder 的接口以构造和装配该产品的各个部件。
定义并明确它所创建的表示,即针对不同的商业逻辑,具体化复杂对象的各部分的创建
提供一个检索产品的接口。
Director
Product
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
实际使用时,可以根据需要简化或删减参与者,最小结构至少包括Builder和Product。
代码实现
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 public class User { private final String firstName; private final String lastName; private final int age; private final String phone; private final String address; private User (UserBuilder builder) { this .firstName = builder.firstName; this .lastName = builder.lastName; this .age = builder.age; this .phone = builder.phone; this .address = builder.address; } public String getFirstName () { return firstName; } public String getLastName () { return lastName; } public int getAge () { return age; } public String getPhone () { return phone; } public String getAddress () { return address; } @Override public String toString () { return "User: " + this .firstName + ", " + this .lastName + ", " + this .age + ", " + this .phone + ", " + this .address; } public static class UserBuilder { private final String firstName; private final String lastName; private int age; private String phone; private String address; public UserBuilder (String firstName, String lastName) { this .firstName = firstName; this .lastName = lastName; } public UserBuilder age (int age) { this .age = age; return this ; } public UserBuilder phone (String phone) { this .phone = phone; return this ; } public UserBuilder address (String address) { this .address = address; return this ; } public User build () { User user = new User (this ); validateUserObject(user); return user; } private void validateUserObject (User user) { } } }
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 34 public static void main (String[] args) { User user1 = new User .UserBuilder("Lokesh" , "Gupta" ) .age(30 ) .phone("1234567" ) .address("Fake address 1234" ) .build(); System.out.println(user1); User user2 = new User .UserBuilder("Jack" , "Reacher" ) .age(40 ) .phone("5655" ) .build(); System.out.println(user2); User user3 = new User .UserBuilder("Super" , "Man" ) .build(); System.out.println(user3); }
JDK源码中的实现 JDK 里不少链式 API 都带着建造者模式的影子,例如:
这些方法都返回 this,写完接着接下一个调用,最后 toString() 收口。顺带纠一个常见混淆:Appendable 家族只包含 StringBuilder、StringBuffer、CharBuffer、Writer 这些「字符」类,java.nio 的七个 buffer 里只有 CharBuffer 实现了 Appendable,其余 buffer 的 put() 只是链式风格而已(JDK 25 的 All Known Implementing Classes 可查)。
1 2 3 4 5 6 7 8 9 StringBuilder builder = new StringBuilder ("Temp" );String data = builder.append(1 ) .append(true ) .append("friend" ) .toString(); System.out.println(data);
以及 javax.swing.GroupLayout.Group#addComponent()
Lombok中 @Builder注解内部实现 1 2 3 4 5 6 7 @Builder public class User { private final Integer code = 200 ; private String username; private String password; }
Builder内部帮我们做了什么
创建一个名为ThisClassBuilder的内部静态类,并具有和实体类形同的属性(称为构建器)。
在构建器中:为实体类中的非静态字段生成对应属性;声明处已初始化过的 final 字段除外 (例中 code 就不进构建器,字段本体保留在 User 里);非 final 但带初始值的字段会进构建器,只是初值被忽略——想要默认值得用 @Builder.Default。
在构建器中:创建一个无参的default构造函数。
在构建器中:对于实体类中的每个参数,都会对应创建类似于setter的方法,只不过方法名与该参数名相同。 并且返回值是构建器本身(便于链式调用),如上例所示。
在构建器中:一个build()方法,调用此方法,就会根据设置的值进行创建实体对象。
在构建器中:同时也会生成一个toString()方法。
在实体类中:会创建一个builder()方法,它的目的是用来创建构建器。
编译后 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 class User { private final Integer code = 200 ; private String username; private String password; User(String username, String password) { this .username = username; this .password = password; } public static User.UserBuilder builder () { return new User .UserBuilder(); } public static class UserBuilder { private String username; private String password; UserBuilder() {} public User.UserBuilder username (String username) { this .username = username; return this ; } public User.UserBuilder password (String password) { this .password = password; return this ; } public User build () { return new User (this .username, this .password); } public String toString () { return "User.UserBuilder(username=" + this .username + ", password=" + this .password + ")" ; } } }
系列索引:设计模式系列