您现在的位置是:首页 >技术交流 >设计模式之建造者模式网站首页技术交流
设计模式之建造者模式
1、什么是建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
2、代码演示
主机类:
public class Host {
private String CPU;//CPU型号
private String Memory;//内存条型号
private String disk;//磁盘型号
public String getCPU() {
return CPU;
}
public Host(){
}
public Host(Host host){
this.CPU=host.CPU;
this.Memory=host.Memory;
this.disk=host.disk;
}
public void setCPU(String CPU) {
this.CPU = CPU;
}
public String getMemory() {
return Memory;
}
public void setMemory(String memory) {
Memory = memory;
}
public String getDisk() {
return disk;
}
public void setDisk(String disk) {
this.disk = disk;
}
}
建造者抽象类:
public abstract class Builder {//建造者抽象类
public Host host=new Host();
public Builder(){
host=new Host();
}
public abstract void buildCPU();
public abstract void buildDisk();
public abstract void buildMemory();
public Host build(){
buildCPU();
buildDisk();
buildMemory();
return new Host(host);
}
}
联想建造者类:
public class LenovoBuilder extends Builder {
@Override
public void buildCPU() {
host.setCPU("联想CPU");
}
@Override
public void buildDisk() {
host.setDisk("联想磁盘");
}
@Override
public void buildMemory() {
host.setMemory("联想内存");
}
}
苹果建造者类:
public class AppleBuilder extends Builder {
@Override
public void buildCPU() {
host.setCPU("苹果CPU");
}
@Override
public void buildDisk() {
host.setDisk("苹果磁盘");
}
@Override
public void buildMemory() {
host.setMemory("苹果内存");
}
}
可见,如果我们想获取一个联想的主机,那么我们直接调用它的建造者类的build方法即可:
public class Test {
public static void main(String[] args) {
Builder builder=new LenovoBuilder();
Host build = builder.build(); //直接获取联想的主机
System.out.println("内存为:"+build.getMemory());
System.out.println("CPU为:"+build.getCPU());
System.out.println("硬盘为:"+build.getDisk());
}
}
运行结果如下:
可见,我们通过建造者类可以直接获取相关对象,而不用去关心它内部是如何实现的。
3、优缺点
优点:
①建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在指挥者类中对整体而言可以取得比较好的稳定性。
②在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
③可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
④建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。符合开闭原则。
缺点:
造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
4、模式扩展
大家可以看到,对于我们上述的建造者模式,比较简单单一,通常适用于要一个对象所有配件都来自于同一个厂家(同一个builder),因此,如果我们想组合那种混合的电脑,比如:CPU我觉得苹果好,想用苹果的CPU;内存我觉得三星的好,想用三星的内存;硬盘我觉得联想的好,想用联想的硬盘。那这种建造模式应该怎么实现呢?以下我们提供一种实现思路:
Host类:
public class Host {
private String CPU;//CPU型号
private String Memory;//内存条型号
private String disk;//磁盘型号
public Host(Builder builder){
this.CPU=builder.CPU;
this.Memory=builder.Memory;
this.disk=builder.disk;
}
public static class Builder{
private String CPU;//CPU型号
private String Memory;//内存条型号
private String disk;//磁盘型号
public Builder setCPU(String CPU){
this.CPU=CPU;
return this;
}
public Builder setMemory(String memory){
this.Memory=memory;
return this;
}
public Builder setDisk(String disk){
this.disk=disk;
return this;
}
public Host build(){
return new Host(this);
}
}
@Override
public String toString() {
return "Host{" +
"CPU='" + CPU + ''' +
", Memory='" + Memory + ''' +
", disk='" + disk + ''' +
'}';
}
}
测试类:
public class Test {
public static void main(String[] args) {
Host build = new Host.Builder()
.setDisk("联想Disk")
.setCPU("苹果CPU")
.setMemory("三星Memory")
.build();
System.out.println("电脑配置如下:");
System.out.println(build.toString());
}
}
运行结果如下:
大家可以发现,上述代码风格是不是很像大家之前接触一些框架提供的“Builder”,没错,那些框架的实现其实也是这种思路。
5、模式对比
大家可能会发现,诶,这种模式和工厂模式有啥区别呢?
5.1 工厂方法模式VS建造者模式
工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。
我们举个简单例子来说明两者的差异,如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后再把内裤外穿,于是一个超人就诞生了。
5.2 抽象工厂模式VS建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。
建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。