1、 概述
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
2、使用场景
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
3、如何实现
建造者模式有两个版本,一个较为简单,也是最常用的,先看看这个版本。
我们用用户信息来描述建造者模式,其中,id,name,password是必须的字段,address和email是不必须的。
User类
public class User {
private String id;
private String name;
private String password;
private String address;
private String email;
private User(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.password = builder.password;
this.address = builder.address;
this.email = builder.email;
}
public static class Builder {
private String id;
private String name;
private String password;
private String address;
private String email;
public Builder(String id, String name, String password){
this.id = id;
this.name = name;
this.password = password;
}
public Builder setAddress(String address){
this.address = address;
return this;
}
public Builder setEmail(String email){
this.email = email;
return this;
}
public User build(){
return new User(this);
}
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", address='" + address + '\'' +
", email='" + email + '\'' +
'}';
}
}
客户端调用
public class Client {
public static void main(String[] args) {
User user = new User.Builder("10455643434", "gzj", "123123")
.setAddress("xinhexian")
.build();
System.out.println(user.toString());
}
}
另外一种是比较传统的建造者模式
构建者模式UML图如下所示
如上图所示,建造者模式有4个角色。
Product: 最终要生成的对象,例如 User实例。
Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
ConcreteBuilder: Builder的实现类。
Director: 决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。
用传统建造者模式实现一遍
User类(Product)
public class User {
private String id;
private String name;
private String password;
private String address;
private String email;
public User(String id, String name, String password){
this.id = id;
this.name = name;
this.password = password;
}
public void setAddress(String address) {
this.address = address;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", address='" + address + '\'' +
", email='" + email + '\'' +
'}';
}
}
UserBuilder类(Builder)
public abstract class UserBuilder {
public abstract void setAddress();
public abstract void setEmail();
public abstract User getUser();
}
UserA(ConcreteBuilder)
public class UserA extends UserBuilder {
private User user;
public UserA(String id, String name, String password){
user = new User(id, name, password);
}
@Override
public void setAddress() {
user.setAddress("中国");
}
@Override
public void setEmail() {
user.setEmail("qweqwe@123.com");
}
@Override
public User getUser() {
return user;
}
}
UserB
public class UserB extends UserBuilder {
private User user;
public UserB(String id, String name, String password){
user = new User(id, name, password);
}
@Override
public void setAddress() {
user.setAddress("日本");
}
@Override
public void setEmail() {
user.setEmail("bagayalu@riben.cn");
}
@Override
public User getUser() {
return user;
}
}
UserDirector(director)
public class UserDirector {
public void makeUser(UserBuilder builder){
builder.setAddress();
builder.setEmail();
}
}
测试类
public class Client {
public static void main(String[] args) {
UserDirector director = new UserDirector();
UserBuilder builder = new UserA("187345243", "sad", "35345");
director.makeUser(builder);
User user = builder.getUser();
System.out.println(user.toString());
}
}
优点:
- 使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 具体的建造者类之间是相互独立的,这有利于系统的扩展。
- 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
缺点:
如果要增加产品细节时,比如我要给用户类增加一个性别,那就要大改。
所以适用范围是当复杂对象的部件相对稳定,不会发生变化时才可以用创建者模式。