package jzone.designpatern.builder; public class User { private int id; private String name; private int sex; private int door; private String address; public User(Builder builder) { id = builder.id; name = builder.name; sex = builder.sex; door = builder.door; address = builder.address; } public void print() { System.out.print("User " + name + " 's id is " + id + " , sex is " + (sex == 0 ? "Male" : "Female") + " , door is " + door + " , address is " + address + "."); } public static class Builder { // Unchangeable Parameters private final int id; private final String name; // Changeable Parameters private int sex; private int door; private String address; public Builder(int id, String name) { this.id = id; this.name = name; sex = 0; door = 0; address = null; } public Builder sex(int sex) { this.sex = sex; return this; } public Builder door(int door) { this.door = door; return this; } public Builder address(String address) { this.address = address; return this; } public User build() { return new User(this); } } } package jzone.designpatern.builder; public class BuildStudent { public static void main(String[] args) { User stu = new User.Builder(2010, "Hesey").sex(0).door(10) .address("Software College").build(); stu.print(); } }
采用构造函数的方式来对对象的参数进行初始化带来的问题是可读性很差,必须很清楚构造函数中各个参数是什么及其顺序,程序员或许会知道这可能是在创建一个用户对象并作其参数的初始化,但是参数究竟意味着什么,就必须去看源代码或是查阅文档
可读性更强的解决方案——通过一连串的get,set方法对参数进行获取或设置,各个参数的初始化被放到了不同的方法调用中,这会导致严重的线程不安全问题(构造函数则不存在这个问题)。对象在一连串的set方法中,可能会出现状态不一致的情况
Builder模式则是兼具了构造函数的线程安全性和JavaBeans可读性优点。其主要原理是在类的内部构造一个内部类——Builder类,Builder类通过类似set的方法对参数进行初始化,最后调用build()方法创建其所属类的新对象并将其自身返回给这个新对象,一次性完成构造工作。
构造函数构造了两个必要的参数(学号和姓名)之后,可以用类似于JavaBeans的set方法来初始化参数,事实上这种方式比set更为清晰明了,有如直接访问对象参数一般(实际还是方法调用)。
在构造复杂对象时,建议采用这种方式。