设计模式之建造者模式
# 设计模式之建造者模式
# 一、简介
使用多个简单的对象一步一步构建成一个复杂的对象。
一些基本部件不会变,而其组合经常变化的时候,可以考虑使用建造者模式。
# 二、实现方式
# 1、传统Builder模式
传统的建造者模式包含四个角色:
Product(产品) 一个具体的产品对象
Builder(抽象建造者) 一个创建
Product
对象的各个部件的接口/抽象类ConcreteBuilder(具体建造者) 实现了
Builder
接口,具体创建对象的各个部件Director(指挥者) 使用
Builder
接口的对象。有两个作用:1、对客户端隐藏产品对象的创建过程
2、控制产品对象的创建过程
具体实现
目标产品Computer类
public class Computer { private String cpu;//必须 private String ram;//必须 private int usbCount;//可选 private String keyboard;//可选 private String display;//可选 public Computer(String cpu, String ram) { this.cpu = cpu; this.ram = ram; } public void setUsbCount(int usbCount) { this.usbCount = usbCount; } public void setKeyboard(String keyboard) { this.keyboard = keyboard; } public void setDisplay(String display) { this.display = display; } @Override public String toString() { return "Computer{" + "cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + ", usbCount=" + usbCount + ", keyboard='" + keyboard + '\'' + ", display='" + display + '\'' + '}'; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31抽象建造者类
public abstract class ComputerBuilder { public abstract void setUsbCount(); public abstract void setKeyboard(); public abstract void setDisplay(); public abstract Computer build(); }
1
2
3
4
5
6
7具体建造者类
public class MacComputerBuilder extends ComputerBuilder { private Computer computer = new Computer(); @Override public void setUsbCount() { computer.setUsbCount(2); } @Override public void setKeyboard() { computer.setKeyboard("苹果键盘"); } @Override public void setDisplay() { computer.setDisplay("苹果显示器"); } @Override public Computer build() { return computer; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20指导者类(Director)
public class ComputerDirector { public void makeComputer(ComputerBuilder builder){ builder.setUsbCount(); builder.setDisplay(); builder.setKeyboard(); } }
1
2
3
4
5
6
7测试类
public static void main(String[] args) { ComputerDirector director=new ComputerDirector();//1 ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2 director.makeComputer(builder);//3 Computer macComputer=builder.build();//4 System.out.println("mac computer:"+macComputer.toString()); }
1
2
3
4
5
6
7
# 2、简化Builder模式
传统的builder
模式存在许多变种,其中一种省略了director
这个角色,将构建算法交给了client
端,其次将builder
写到了要构建的产品类里面,最后采用了链式调用
代码实现如下:
public class Computer {
private final String cpu;//必须
private final String ram;//必须
private final int usbCount;//可选
private final String keyboard;//可选
private final String display;//可选
private Computer(Builder builder){
this.cpu=builder.cpu;
this.ram=builder.ram;
this.usbCount=builder.usbCount;
this.keyboard=builder.keyboard;
this.display=builder.display;
}
public static class Builder{
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Builder(String cup,String ram){
this.cpu=cup;
this.ram=ram;
}
public Builder setUsbCount(int usbCount) {
this.usbCount = usbCount;
return this;
}
public Builder setKeyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder setDisplay(String display) {
this.display = display;
return this;
}
public Computer build(){
return new Computer(this);
}
}
//省略getter方法
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
测试代码:
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
2
3
4
5
# 三、应用场景
# 1、StringBuilder中的建造者模式:StringBuilder和StringBuffer
我们先看一下这两个类的结构图:
其中Appendable
接口定义了几种append
方法,因此,它是一个抽象建造者
AbstractStringBuilder
虽然是一个抽象类,但是它实现了Appendable
接口,并重写了append
方法。因此,它是一个具体建造者
StringBuilder
和StringBuffer
继承了AbstractStringBuilder
,它们通过调用父类AbstractStringBuilder
的append
方法的形式重写了append
方法。因而,它们是具体建造者,同时又充当了指挥者(Director
)的角色
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
2
3
4
5
# 2、MyBatis中的建造者模式:SqlSessionFactoryBuilder
SqlSessionFactory
是通过SqlSessionFactoryBuilder
创建的,代码如下:
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
2
3
SqlSessionFactory
的创建需要Configuration
,Configuration
的属性非常多,创建起来非常繁杂,便通过XMLConfigBuilder
的parse()
方法构建Configuration
实例
XMLConfigBuilder
负责创建 Configuration
的各个部件,如下图所示。
private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
Properties settings = this.settingsAsProperties(root.evalNode("settings"));
this.loadCustomVfs(settings);
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
this.settingsElement(settings);
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在上面的例子中:
Configuration
相当于产品。
XMLConfigBuilder
负责创建复杂对象Configuration
,相当于具体建造者。
XMLConfigBuilder
继承自 BaseBuilder
,所以BaseBuilder
相当于是抽象建造者。
SqlSessionFactoryBuilder
调用XMLConfigBuilder
中构造对象的方法,相当于指挥者。