好比 Person 類,包含 id、姓名、性別、身高、體重屬性。爲了方便建立對象,咱們通常使用全部屬性做爲參數提供一個最全的構造方法,而後按需提供部分屬性的若干構造方法。代碼以下:面試
package constxiong.interview.design;
/** * 對象人 * @author ConstXiong */public class Person {
/** * id */ private final int id; /** * 姓名 */ private final String name; /** * 性別 */ private final String sex; /** * 身高 */ private final Double height; /** * 體重 */ private final Double weight; public Person(int id, String name) { this(id, name, null); } public Person(int id, String name, String sex) { this(id, name, sex, null); } public Person(int id, String name, String sex, Double height) { this(id, name, sex, height, null); }
public Person(int id, String name, String sex, Double height, Double weight) { this.id = id; this.name = name; this.sex = sex; this.height = height; this.weight = weight; }}
當咱們須要建立一個只知道 id、姓名、性別的對象時,調用第 2 個構造方法便可安全
Person person = new Person(1, "ConstXiong", "男");
這樣作存在問題:示例中才 5 個參數,實際開發中隨着參數的增多,建立對象會愈來愈困難,須要肯定參數的數量與構造方法中的位置;代碼可讀性不好;容易參數顛倒且很難排查。
爲解決上述問題,會有第 2 種作法,提供默認構造方法與屬性的 set 方法。session
package constxiong.interview.design;
/** * 對象人 * @author ConstXiong */public class Person {
/** * id */ private int id; /** * 姓名 */ private String name; /** * 性別 */ private String sex; /** * 身高 */ private Double height; /** * 體重 */ private Double weight; public Person() { }
public void setId(int id) { this.id = id; }
public void setName(String name) { this.name = name; }
public void setSex(String sex) { this.sex = sex; }
public void setHeight(Double height) { this.height = height; }
public void setWeight(Double weight) { this.weight = weight; }}
這種的方式 Person 對象能夠這樣建立app
Person person = new Person();person.setId(1);person.setName("ConstXiong");person.setSex("男");person.setHeight(1.70);person.setWeight(150.0);
這樣作解決了構造方法多個參數和可讀性的問題,可是引入了新的問題,就是沒法作到屬性參數在構造完以後是不可改變的,致使存在數據不安全的問題。
第 3 種方式,使用 Builder 模式。代碼以下ide
package constxiong.interview.design;
/** * 對象人 * @author ConstXiong */public class Person {
/** * id */ private final int id; /** * 姓名 */ private final String name; /** * 性別 */ private final String sex; /** * 身高 */ private final Double height; /** * 體重 */ private final Double weight; public static class Builder { private int id; private String name; private String sex; private Double height; private Double weight; public Builder() { } public Builder id(int id) { this.id = id; return this; } public Builder name(String name) { this.name = name; return this; } public Builder sex(String sex) { this.sex = sex; return this; } public Builder height(Double height) { this.height = height; return this; } public Builder weight(Double weight) { this.weight = weight; return this; } public Person build() { return new Person(this); } } private Person(Builder builder) { this.id = builder.id; this.name = builder.name; this.sex = builder.sex; this.height = builder.height; this.weight = builder.weight; }}
建立 Person 對象的代碼性能
Person person = new Person.Builder() .id(1) .name("ConstXiong") .sex("男") .height(1.70) .weight(150.0) .build();
Builder 模式須要注意是,Builder 類是靜態內部類、類的構造方法是 private 的且參數爲 Builder 對象。
Builder 模式不只能夠解決構造過程數據安全、參數過多、可讀性的問題,還能夠自動填充參數、生成對象前對參數之間的關係進行合法校驗等...
固然 Builder 模式也帶了新的問題:ui
因此說,軟件開發通常沒有完美的解決方法,只有不一樣場景的最優解決辦法;一種方法能解決某些問題,必然帶來其餘問題。
Builder 模式就很是適合使用較多參數構造對象、須保證對象構造後的屬性字段安全的場景。
PS:Java 面試題彙總在:這裏this