简介
建造者模式隐藏了创建过程,让客户端调用变的简单,使一个复杂的类可以被简单的创建,他属于创建型设计模式。他可以解决以下问题:
1、创建一个复杂的类时,他的创建顺序不一样。
2、如果让一个复杂的类创建变的简单?
如果不适用建造者模式,那么你创建一个类需要在应用层去组装这个类,这样会出现很多冗余代码,而且不灵活,建造者模式可以把这些复杂的创建过程进行封装。在Builder对象中封装了复杂的对象创建,类的创建交给Builder来完成,而不是直接创建复杂的类。建造者模式主要是将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。
适用场景
1、如果一个对象有非常复杂的内部结构
2、想把复杂对象的创建和表现分离
优点
1、封装性好,创建和使用分离
2、扩展性好,建造类之间独立,一定程度上解耦,允许你修改产品内部表现
缺点
1、产生多余的Builder对象
2、要求builder类是可变的
3、类的数据成员不能保证被初始化
4、产品内部发生变化,建造者都要修改,成本较大
5、依赖注入可能不太支持
示例代码
先看下建造者的类图,示例是创造汽车的例子,来看看具体的代码:
汽车类:
public class Car {
private String color;
private int wheels;
public Car() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getWheels() {
return wheels;
}
public void setWheels(int wheels) {
this.wheels = wheels;
}
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", wheels=" + wheels +
'}';
}
}
汽车的建造者抽象类
public abstract class CarBuilder {
public abstract void buildColor(String color);
public abstract void buildWheels(int wheels);
public abstract Car makeCar();
}
建造者的实现类
public class CarBuilderImpl extends CarBuilder {
private Car car = new Car();
@Override
public void buildColor(String color) {
car.setColor(color);
}
@Override
public void buildWheels(int wheels) {
car.setWheels(wheels);
}
@Override
public Car makeCar() {
return car;
}
}
创建一个主任类,来负责进行创建:
public class CarBuilderDirector {
private CarBuilder carBuilder;
public void setCarBuilder(CarBuilder carBuilder){
this.carBuilder = carBuilder;
}
public Car makeCar(String color,int wheels){
carBuilder.buildColor(color);
carBuilder.buildWheels(wheels);
return carBuilder.makeCar();
}
}
最后是一个测试类:
public class BuilderTest {
public static void main(String[] args) {
CarBuilder carBuilder = new CarBuilderImpl();
CarBuilderDirector carBuilderDirector = new CarBuilderDirector();
carBuilderDirector.setCarBuilder(carBuilder);
Car car = carBuilderDirector.makeCar("红色",4);
System.out.println(car);
}
}
在这个例子中,出现了很多类,如主任类,Builder相关的类,那么有没有办法简化呢?
下面在来看个例子:
通过链式方式,减少了很多类。
public class Car {
private String color;
private int wheels;
public Car(CarBuilder carBuilder) {
this.color = carBuilder.color;
this.wheels = carBuilder.wheels;
}
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", wheels=" + wheels +
'}';
}
public static class CarBuilder{
private String color;
private int wheels;
public CarBuilder buildColor(String color){
this.color = color;
return this;
}
public CarBuilder buildWheels(int wheels){
this.wheels = wheels;
return this;
}
public Car build(){
return new Car(this);
}
}
}
测试类:
public class BuilderTest {
public static void main(String[] args) {
Car car = new Car.CarBuilder().buildColor("红色").buildWheels(4).build();
System.out.println(car);
}
}
第一个例子,通过传参来构建builder类,这样容易出现参数传入错误的问题,通过链式的方式,对赋值变的简单,不容易出错。
上面示例源码
源码分析
在很多源码框架中都使用了建造者模式。
jdk中应用
StringBuilder
与StringBuffer
都有用建造者模式,如
StringBuilder的代码
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
StringBuffer的代码
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
guava中应用
ImmutableSet
中也使用了建造者模式,查看部分源码:
public static class Builder<E> extends ImmutableCollection.ArrayBasedBuilder<E> {
public Builder() {
this(DEFAULT_INITIAL_CAPACITY);
}
Builder(int capacity) {
super(capacity);
}
@Override
public Builder<E> add(E element) {
super.add(element);
return this;
}
@Override
public Builder<E> addAll(Iterable<? extends E> elements) {
super.addAll(elements);
return this;
}
@Override
public ImmutableSet<E> build() {
ImmutableSet<E> result = construct(size, contents);
size = result.size();
return result;
}
}
public static <E> Builder<E> builder() {
return new Builder<E>();
}
使用示例:
ImmutableSet set = new ImmutableSet.Builder<>().add("1").build();
System.out.println(set);
spring中应用
BeanDefinitionBuilder
也是使用了建造者模式,如:
public static BeanDefinitionBuilder genericBeanDefinition() {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new GenericBeanDefinition();
return builder;
}
public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName) {
return rootBeanDefinition(beanClassName, null);
}
mybatis中应用
SqlSessionFactoryBuilder
也使用了建造者模式,可以创建SqlSessionFactory
类,如:
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment) {
return build(reader, environment, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
}
在mybatis中大量使用了建造者模式,如XMLConfigBuilder
、XMLMapperBuilder
、MapperAnnotationBuilder
、CacheBuilder
等等。
注意:本文归作者所有,未经作者允许,不得转载