构建者模式
认识
- 构建者模式可以分步骤构建复杂对象,构建的过程是固定不变的director实现,变化的部分放到builder中实现,定义多个builder的实现类实现不同的过程,而director调用的builder是不变化的
- director类似一个工厂模式的实现,在director调用不同的builder实现进行构造。保证director的逻辑不要变化,将变化封装到builder实现类中。
思考
构建者模式是将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。抽象工厂可以操作多个产品,而构建者只可以操作一个产品
与工厂模式区别是,工厂模式创建对象时并不需要客户端提供特别多的信息,而构建者模式需要客户端提供创建对象的细节内容。
优缺点
优点
- 暴露了创建对象的细节,这样使得建造者模式更加灵活,可替换。
- 链式创建对象,具有分步骤创建对象的思想
- 客户端和和产品实现类解耦
缺点
- 将对象的创建细节暴露
使用场景
- 需要生成的产品对象有复杂的内部结构。如果很简单的话,那么使用这个模式可能就没有必要了
- 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序
- 使用链式结构
UML图
- 产品类(Product):一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
- 抽象建造者(Builder):引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
- 建造者(ConcreateBuilder):实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
- 导演类(Director):负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。
代码实现
class Product {
private String name;
private String type;
public void showProduct(){
System.out.println("名称:"+name);
System.out.println("型号:"+type);
}
public void setName(String name) {
this.name = name;
}
public void setType(String type) {
this.type = type;
}
}
abstract class Builder {
public abstract void setPart(String arg1, String arg2);
public abstract Product getProduct();
}
class ConcreteBuilder extends Builder {
//构建器中new一个产品对象,也可以通过构造方法传入
private Product product = new Product();
//提供返回产品的方法
public Product getProduct() {
return this.product;
}
//buildName 返回this.product 链式结构
public Product buildName(String name) {
this.product.setName(name);
return this.product;
}
//buildType 返回this.product 链式结构
public Product buildType(String type) {
this.product.setType(type);
return this.product;
}
}
/*
* Director通过Builder创建对象
* Director 也可以理解为一个工厂模式的实现
*/
public class Director {
private Builder builder = new ConcreteBuilder();
public Product getAProduct(){
builder.buildName("宝马汽车").build("X7");
return builder.getProduct();
}
public Product getBProduct(){
builder.buildName("奥迪汽车").build("Q5");
return builder.getProduct();
}
}
/**
* 客户端调用Director
*/
public class Client {
public static void main(String[] args){
Director director = new Director();
Product product1 = director.getAProduct();
product1.showProduct();
Product product2 = director.getBProduct();
product2.showProduct();
}
}
源码例子
mybatis中大量使用了构建者模式,例如构造Configuration对象
public abstract class BaseBuilder {
protected final Configuration configuration;
protected final TypeAliasRegistry typeAliasRegistry;
protected final TypeHandlerRegistry typeHandlerRegistry;
public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
public Configuration getConfiguration() {
return configuration;
}
}
//在XMLConfigBuilder对Configuration的各个组件进行组装
public class XMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private XPathParser parser;
private String environment;
private ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectionFactoryElement(root.evalNode("reflectionFactory"));
settingsElement(root.evalNode("settings"));
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
}
这种构造器模式的使用,实现了显示与构建行为的分离
public final class Environment {
private final String id;
private final TransactionFactory transactionFactory;
private final DataSource dataSource;
public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
if (id == null) {
throw new IllegalArgumentException("Parameter 'id' must not be null");
}
if (transactionFactory == null) {
throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null");
}
this.id = id;
if (dataSource == null) {
throw new IllegalArgumentException("Parameter 'dataSource' must not be null");
}
this.transactionFactory = transactionFactory;
this.dataSource = dataSource;
}
public static class Builder {
private String id;
private TransactionFactory transactionFactory;
private DataSource dataSource;
public Builder(String id) {
this.id = id;
}
public Builder transactionFactory(TransactionFactory transactionFactory) {
this.transactionFactory = transactionFactory;
return this;
}
public Builder dataSource(DataSource dataSource) {
this.dataSource = dataSource;
return this;
}
public String id() {
return this.id;
}
public Environment build() {
return new Environment(this.id, this.transactionFactory, this.dataSource);
}
}
public String getId() {
return this.id;
}
public TransactionFactory getTransactionFactory() {
return this.transactionFactory;
}
public DataSource getDataSource() {
return this.dataSource;
}
}
public class client{
public void run(){
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
Environment ev = environmentBuilder.build();
}
}