builder模式适合于实例化参数多且不固定的对象的情况。
举个例子,当你注册某个网站的用户,填写信息的时候,必填的只有用户名、密码而其他的诸如生日、手机号码、电子邮件地址、性别等等都是选填的。假如你是开发此网站的程序员,你要如何定义“user”这个对象?
一般情况下都会有如下定义法:
public class user
{
/**
*必填
*/
private String uname;
private String upwd;
/**
*选填
*/
private String email;
private String phone;
private int gender;
private String birthday;
public user()
{
}
public user(String uname, String upwd)
{
this.uname = uname;
this.upwd = upwd;
}
.......
}
这里有一个问题,当我们需要三个参数的构造器的时候呢?我们就加一个三个参数的构造器呗,大不了写一个把所有参数都加上的构造器嘛。现在一共有6个参数,当我们实例化一个用户的时候代码是这样的:
User user = new User("andy", "123456", "123444@pp.com", "1367844124", "male", "1982-09-03");
此时我们会发现,参数列表中有许多的参数的类型都是一样的,某些时候我们可能很难去区分。再说你写非常多的构造器,也是比较麻烦的事情。(尤其在参数更多的情况下)
既然都用到JAVABEAN了为什么不将getter和setter一起写上呢?其实这个也是一个好办法,现实中我们也都是这么做的。但是我们用setter进行属性赋值的时候,现实中我们的对象已经被创建出来了,因为对象创建的状态和属性赋值的两步是完全分开的,某些时候当我们正在赋值的时候,我们赋予的值可能会被其他线程改变。(具体的例子也不举了,详细可见《effective Java》第二版)
再看一下这种写法:
User user = new User.Builder("andy", "1234")
.email("andy@pp.com")
.phone("15623412545")
.build();
我们可以随意选择builder.后面的方法,而且都是具名的方法,是不是感觉清爽的多了?对,这就是builder模式。
让我们看一下完整写法:
public class user
{
/**
*必填
*/
private String uname;
private String upwd;
/**
*选填
*/
private String email;
private String phone;
private int gender;
private String birthday;
public static class Builder
{
/**
*必填
*/
private String uname;
private String upwd;
/**
*选填,但是你可以指定默认值或者限制条件,于setter方法一样
*/
private String email;
private String phone;
private int gender;
private String birthday;
public Builder email(String email)
{
this.email = email;
return this;
}
public Builder phone(String phone)
{
this.phone= phone;
return this;
}
public Builder gender(String gender)
{
this.gender= gender;
return this;
}
public Builder birthday(String birthday)
{
this.birthday= birthday;
return this;
}
public User build()
{
return new User(this);
}
}
private user(Builder builder)
{
this.uname = builder.uname;
this.upwd = builder.upwd;
this.email = builder.email;
this.phone = builder.phone;
this.gender = builder.gender;
this.birthday = builder.birthday;
}
}
大致思路就是,利用一个静态内部类Builder构建对User类属性的赋值,最后通过build()方法一次性进行构建。
内部类中的this指代的是内部类的对象,外部类中的this指代的是外部类中的对象。