本文共 4195 字,大约阅读时间需要 13 分钟。
建造者模式也叫生成器模式,具有封装性、易扩展等优势,其定义为:将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
假定我们现在接到一个需求,要造出一辆奔驰,那么我们可以做如下设计:
首先,本着抽象原则,我们肯定是会先定义一个接口Car,里面包含了车子都会有的部件,如下:
public abstract class Car { /** 引擎 */ private String engine; /** 车身 */ private String bodywork; /** 底盘 */ private String chassis; /** 轮胎 */ private String tyre; @Override public String toString() { return new ToStringBuilder(this) .append("engine", engine) .append("bodywork", bodywork) .append("chassis", chassis) .append("tyre", tyre) .toString(); } //省略get set方法。。。}
接下来,来定义我们的奔驰,此处奔驰与普通车的特殊在于他有一个全景天窗,我们来看Benz:
public class Benz extends Car { public void sunroof () { System.out.println("我有全景天窗!"); }}
要建造一辆奔驰,那么接下来我们需要一个建造者来完成这件事情,如下先定义出通用建造者的接口:
public interface ICarBuilder { /** * 建造引擎 */ void buildEngine(); /** * 建造车身 */ void buildBodywork(); /** * 建造底盘 */ void buildChassis(); /** * 建造轮胎 */ void buildTyre(); /** * 建造车子 */ Car build();}
接下来我们来实现奔驰建造者,用以制造我们的奔驰:
public class BenzBuilder implements ICarBuilder { private static Car benz; public BenzBuilder() { } public void buildEngine() { benz.setEngine("奔驰引擎"); } public void buildBodywork() { benz.setBodywork("奔驰车身"); } public void buildChassis() { benz.setChassis("奔驰底盘"); } public void buildTyre() { benz.setTyre("奔驰轮胎"); } public Car build () { benz = new Benz(); this.buildEngine(); this.buildBodywork(); this.buildChassis(); this.buildTyre(); return benz; }}
通过奔驰的建造者,我们只要调用build方法,就可以实现奔驰的建造,这是一种最简易化的建造者模式。我们来看一下建造奔驰:
public static void main(String[] args) { ICarBuilder benzBuilder = new BenzBuilder(); Car benz = benzBuilder.build(); System.out.println(benz);}
输出结果:
org.white.common.test.design.model.Benz@3af49f1c[engine=奔驰引擎,bodywork=奔驰车身,chassis=奔驰底盘,tyre=奔驰轮胎]
可以看到奔驰已经建造成功,那么接下来,加入又需求我们建造一辆沃尔沃,我们怎么办呢?接下来就要用到完整版的建造者模式了,类图如下:
这里引入了Director类来作为一个控制器,根据不同的指令来建造不同的车,这里需要对上面BenzBuilder类作如下修改:
/** 构造方法中新建对象 */ public BenzBuilder() { benz = new Benz(); } /** build方法不再自行构建,责任交还给Director类,之前是自己充当了Director类的职责 */ public Car build () { return benz; }
接下来来看CarDirector类的代码如下:
public class CarDirector { /** * 使用不同的建造器建造不同的车 */ public Car construct(ICarBuilder builder) { builder.buildEngine(); builder.buildBodywork(); builder.buildChassis(); builder.buildTyre(); return builder.build(); }}
可以通过代码看出,我们传入奔驰的建造器就可以建造一台奔驰,那么按现在的代码结构这里我们要建造一台沃尔沃,只需要新加一个Volvo类和一个VolvoBuilder类就可以了,不会对原有代码造成影响,后续不论造什么车,都可以直接加上各自的建造器和各自的车实体类就可以完成,不需要修改原有代码实现,这样就会获得一个良好的扩展性。接下来我们来看建造一台沃尔沃所需代码:
首先是Volo类:
public class Volvo extends Car { public void safe () { System.out.println("我有自动驾驶系统,我很安全!"); }}
接下来是VolvoBuilder类:
public class VolvoBuilder implements ICarBuilder { private static Car volvo; public VolvoBuilder() { volvo = new Volvo(); } public void buildEngine() { volvo.setEngine("沃尔沃引擎"); } public void buildBodywork() { volvo.setBodywork("沃尔沃车身"); } public void buildChassis() { volvo.setChassis("沃尔沃底盘"); } public void buildTyre() { volvo.setTyre("沃尔沃轮胎"); } public Car build() { return volvo; }}
接下来写测试代码测试是否建造成功:
public static void main(String[] args) { CarDirector director = new CarDirector(); Car benz = director.construct(new BenzBuilder()); Car volvo = director.construct(new VolvoBuilder()); System.out.println(benz.toString()); System.out.println(volvo.toString());}
运行结果如下
org.white.common.test.design.model.Benz@3af49f1c[engine=奔驰引擎,bodywork=奔驰车身,chassis=奔驰底盘,tyre=奔驰轮胎]org.white.common.test.design.model.Volvo@19469ea2[engine=沃尔沃引擎,bodywork=沃尔沃车身,chassis=沃尔沃底盘,tyre=沃尔沃轮胎]
可以看到奔驰和沃尔沃都建造成功了。
下面来总结建造者模式的优点:
欢迎关注个人博客:blog.scarlettbai.com