将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Builder模式是一步一步创建一个复杂对象的创建型模式,它允许使用者在不知道内部建造细节的情况下,可以更精细的控制对象的构造流程。该模式是为了将构建复杂对象的过程和它的部件解耦,是的构建过程和不见得表示隔离开来。
因为一个复杂的对象有很多大量组成部分,如电脑,有主机,显示器,操作系统,还有各种小零件等,如何将这些不见组建成一台电脑,这个装配过程很漫长,也很复杂,为了在构建过程中对外部隐藏实现细节,就可以使用Builder模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,两者之间的耦合也降到最低。
建造者模式是一种创建型设计模式。其主要优点如下:
缺点:
适用环境:
建造者模式包含如下角色:
builder(抽象接口): 为创建一个产品对象的各个部件指定抽象接口。
ConcreteBuilder(抽象接口的具体实现): 实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
Director(接口的构造者和使用者): 构造一个使用Builder接口的对象。
Product(被构造的复杂对象): ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
建造者模式中有原型写法和链式写法。
原型写法:
实体User类(Product)
public class User {
String id;
String name;
String password;
String phone;
//set/get方法
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
抽象建造者/建造者接口(Builder)
public interface Build {
void makeId(String val);
void makeName(String val);
void makePassword(String val);
void makePhone(String val);
User makeUser();
}
具体建造者(BuilderImpl)
public class AdminBuilder implements Build{
User user=new User();
@Override
public User makeUser(){
return user;
}
@Override
public void makeId(String val) {
user.setId(val);
}
@Override
public void makeName(String val) {
user.setName(val);
}
@Override
public void makePassword(String val) {
user.setPassword(val);
}
@Override
public void makePhone(String val) {
user.setPhone(val);
}
}
Admin指导建造者创建User(Director)
public class Admin {
private AdminBuilder adminBuilder;
public void setAdminBuilder(AdminBuilder adminBuilder) {
this.adminBuilder = adminBuilder;
}
public User makeUser(String id,String name,String password,String phone){
adminBuilder.makeId(id);
adminBuilder.makeName(name);
adminBuilder.makePassword(password);
adminBuilder.makePhone(phone);
return this.adminBuilder.makeUser();
}
}
具体main类
public static void main(String[] args){
// new具体建造者
AdminBuilder adminBuilder=new AdminBuilder();
Admin admin=new Admin();// new出Admin指导建造者
admin.setAdminBuilder(adminBuilder);// 准备开始建造(不写会报空指针)
// 根据Admin的建造方法创建User
User user=admin.makeUser("1","张三","123456","88888888");
System.out.println(user.toString());
}
链式写法(推荐):
链式写法是在原型写法的基础上做优化,有些时候Builder
的创建部分有默认值,或者不需要的情况下,而产生不同的Product
,通过以上方式,就需要修改Director
类和Builder
类,再或者根据不同的创建顺序,生成不同的结果,也需要修改Director
类。Director
似乎显得很不稳定和多余。可以通过Builder
自身的调用逻辑来生成Product
,即链式调用
public class User {
String id;
String name;
String password;
String phone;
private User(Builder builder) {
id = builder.id;
name = builder.name;
password = builder.password;
phone = builder.phone;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public String getPhone() {
return phone;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", phone='" + phone + '\'' +
'}';
}
public static final class Builder {
private String id;
private String name;
private String password;
private String phone;
public Builder() {
}
public Builder id(String val) {
id = val;
return this;
}
public Builder name(String val) {
name = val;
return this;
}
public Builder password(String val) {
password = val;
return this;
}
public Builder phone(String val) {
phone = val;
return this;
}
public User build() {
return new User(this);
}
}
}
测试类
public class Test {
public static void main(String[] args) {
User user=new User.Builder().id("1").name("张三").password("123456")
.phone("15820638007").build();
System.out.println(user.toString());
}
}
使用了内部类的方式,将原来自己的类方法变成私有的,而后提供一个静态的内部类来创建对象,通过返回this对象来链式调用。
重点(相比于普通JavaBean的好处):
在建造者模式中,提供一个辅助的静态建造器Builder
(静态内部类),可以在里面set
实体类的属性,与JavaBean
不同的是,建造者是先set
,在通过build
实例化实体类,这样既可以提高代码的阅读性,也可以防止对象没有实例化,就被调用;不会造成不一致性,同时解决了Javabean
模式的线程安全问题。
总结:Director
角色并非多余,能把复杂的Product
创建过程对外隐藏,使Builder
部件和创建过程分离,各方易于扩展,降低了耦合度。当需要对一个对象设置很多属性,此时就能方便的使用链式调用来提高编码速度和代码可读性。