重叠构造器
静态工厂方法和构造器都有一个共同的局限:它们都不能很好地扩展到大量的可选参数。此时一个不错的方案就是重叠构造器模式,此模式的机制原理是:创建第一个构造方法包含必须参数,第二个构造器方法包含一个可选参数,第三个包含两个可选参数,以此类推最后一个构造器包含所有的可选参数。
但是呢,重叠构造器模式虽然可行,但是但遇到大量可选参数时,客户端代码会很难写,而且比较难以阅读。如果API文档缺乏对各参数的描述,客户端代码会很容易因为参数顺序不对而出现意想不到的结果。
代码展示:
package com.stone.designpattern.builder;
/**
* @author Stone Wang
* 重叠构造器的代码展示
*
*/
public class Person {
private String name;
private String phone;
private short age = 0;
private String address = "";
private String email = "";
public Person(final String name, final String phone) {
this(name, phone, (short)0);
}
public Person(final String name, final String phone, short age) {
this(name, phone, age, "");
}
public Person(final String name, final String phone, short age,
final String address) {
this(name, phone, age, address, "");
}
public Person(final String name, final String phone, short age,
final String address, final String email) {
this.name = name;
this.phone = phone;
this.age = age;
this.address = address;
this.email = email;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public short getAge() {
return age;
}
public String getAddress() {
return address;
}
public String getEmail() {
return email;
}
}
JavaBean模式
鉴于重叠构造器造成客户端代码可读性不好的局限,引入Java bean模式。此模式会提供一个带有所有必要参数的构造器和一系列的setter方法,客户端调用最小参数构造器生成类的实例,然后调用setter方法设置可选参数。
代码展示:
package com.stone.designpattern.builder;
/**
* @author Stone Wang
* JavaBean模式的代码展示
*
*/
public class PersonJavaBean {
private String name;
private String phone;
private short age = 0;
private String address = "";
private String email = "";
public PersonJavaBean(final String name, final String phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public short getAge() {
return age;
}
public String getAddress() {
return address;
}
public String getEmail() {
return email;
}
public void setName(final String name) {
this.name = name;
}
public void setPhone(final String phone) {
this.phone = phone;
}
public void setAge(short age) {
this.age = age;
}
public void setAddress(final String address) {
this.address = address;
}
public void setEmail(final String email) {
this.email = email;
}
}
此模式在多线程的情况下会导致对象状态不一致的线程安全问题, 而且还破坏了JavaBean对象不可变的特性。
构建器
鉴于重叠构造器和JavaBean的局限,引入构构建器模式。
它不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂方法), 得到一个builder对象,然后客户端在builder对象上调用类似setter 方法来设置可选参数。
代码展示:
package com.stone.designpattern.builder;
/**
* @author Stone Wang
* 构建器模式的代码展示
*
*/
public class PersonBuilder {
private String name;
private String phone;
private short age = 0;
private String address = "";
private String email = "";
public PersonBuilder(Builder builder) {
this.name = builder.name;
this.phone = builder.phone;
this.age = builder.age;
this.address = builder.address;
this.email = builder.email;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public short getAge() {
return age;
}
public String getAddress() {
return address;
}
public String getEmail() {
return email;
}
public static class Builder{
private String name;
private String phone;
private short age = 0;
private String address = "";
private String email = "";
public Builder(final String name, final String phone) {
this.name = name;
this.phone = phone;
}
public Builder setAge(short age) {
this.age = age;
return this;
}
public Builder setAddress(final String address) {
this.address = address;
return this;
}
public Builder setEmail(final String email) {
this.email = email;
return this;
}
public PersonBuilder build() {
return new PersonBuilder(this);
}
}
}
客户端代码
package com.stone.designpattern.builder;
/**
* @author Stone Wang
*客户端代码展示
*/
public class Main {
public static void main(String[] args) {
// 重叠构造器的客户端
Person p = new Person("Stone", "1888886688", (short)18);
// JavaBean模式的客户端
PersonJavaBean personJavaBean = new PersonJavaBean("Stone", "1888886688");
personJavaBean.setAge((short)18);
//构建器的客户端代码
PersonBuilder.Builder builder = new PersonBuilder.Builder("Stone", "1888886688");
PersonBuilder pb = builder.setAge((short)18).setAddress("Shanghai").build();
}
}