builder模式
假如我们要创建一个对象,而对象有很多字段,一些是必须的,有一些是可选的,现在我们要根据不同的参数组合来写不同的构造函数。
如我们要创建一个用户(user)类,他有必须的字段,id,userName,password还有可选的字段age,email,birthday我们要怎么创建这个类呢!首先我们想到得就是提供不同参数的构造函数!
1 import java.util.Date;
2
3
4 public class User {
5 private String id;
6 private String userName;
7 private String password;
8 private String realName;
9 private String email;
10 private Date birthday;
11 private User(String id,String userName,String password)
12 {
13 this(id,userName,password,null,null,null);
14 }
15 public User(String id,String userName,String password,String realName)
16 {
17 this(id,userName,password,realName,null,null);
18 }
19 public User(String id,String userName,String password,String realName,String email)
20 {
21 this(id,userName,password,realName,email,null);
22 }
23 public User(String id,String userName,String password,String realName,String email,Date birthday)
24 { this.id=id;
25 this.userName=userName;
26 this.password=password;
27 this.realName=realName;
28 this.email=email;
29 this.birthday=birthday;
30 }
31 }
这样的话有很多缺点,不如以后程序扩展时,加一个字段就要改动很多构造参数
于是我们想到了另一种方法,生成setXXX函数来初始化对象
import java.util.Date;
public class User {
private String id;
private String userName;
private String password;
private String realName;
private String email;
private Date birthday;
public void setId(String id) {
this.id = id;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public void setRealName(String realName) {
this.realName = realName;
}
public void setEmail(String email) {
this.email = email;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
这样确实可以在扩展对象的时候减少改动,但又出现了一个问题,就是对象的不唯一,如果对象正在初始化,多个线程去拿这个对象的时候就可能拿到的不一样,我们必须在用另外的机制去保证在对象没有初始化完的情况下不可访问,当然这是高代价的
于是我们有了最后一种方法build模式
import java.util.Date;
public class User {
private String id;
private String userName;
private String password;
private String realName;
private String email;
private Date birthday;
private User(Builder build)
{
this.id=build.id;
this.userName=build.userName;
this.password=build.password;
this.realName=build.realName;
this.email=build.email;
this.birthday=build.birthday;
}
static class Builder{
private String id;
private String userName;
private String password;
private String realName;
private String email;
private Date birthday;
private Builder(String id,String userName,String password)
{
this.id=id;
this.userName=userName;
this.password=password;
}
public Builder realName(String realName)
{
this.realName=realName;
return this;
}
public Builder email(String email)
{
this.email=email;
return this;
}
public Builder birthday(Date birthday)
{
this.birthday=birthday;
return this;
}
public User build()
{
return new User(this);
}
}
他的用法也就
User user=new User.Builder("110", "evan", "123").realName("evanlee").email("XXX@XXX.com").birthday(new Date()).build();
他保证在数据没有初始化之前不会创建对象,这种模式还可以有字段的检验,在初始化参数的时候可一检验数据的合法行,并抛出异常,这样的话只要抛出异常就能中断对象
的初始化
这种模式很灵活,在添加字段只需要添加对应的方法就可以了,但他也带来了额外的开销,但相对于它的可扩张性来说这在有些时候是可以接受的,所以在四个或者四个以上参数的情况下使用种模式吧!
ps:只是本人看法,如有错误,欢迎指正!