定义
在现实世界中的很多东西都是由很多组成部分构成的,比如房子它由砖头、水泥、石灰、钢筋等组成,即一个个简单的组成部分构成了一个复杂的房子。同样在软件系统中也存在很多复杂对象,而复杂对象的一些属性就相当于盖房子的材料,创建对象的过程就相当于盖房子的过程。由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,然后建造者返还一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。
所以建造者模式的定义就是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。生成器模式利用一个导演者对象和具体建造者对象一个一个地建造出所有的零件,从而建造出完整的对象。
组成部分
通过上面对于建造者模式的介绍,可以发现建造者模式应该包含四个部分:
Builder:抽象建造者,定义创建一个Product对象所需要的各个部件的操作。
ConcreteBuilder:具体建造者,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。
Director:指导者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象。
Product:产品,表示被建造者构建的复杂对象,包含多个部件。
栗子
定义一个车子的产品类,假设车子产品类中有轮子、车盖、玻璃等模块,由他们建造组成车子产品。
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/28/22:06 * @Description:车产品 */ public class CarProduct { //车的轮子 private String Wheel; //车的方向盘 private String steeringWheel; //车的车盖 private String Hood; //车的玻璃 private String Windshield; public String getWheel() { return Wheel; } public void setWheel(String wheel) { Wheel = wheel; } public String getSteeringWheel() { return steeringWheel; } public void setSteeringWheel(String steeringWheel) { this.steeringWheel = steeringWheel; } public String getHood() { return Hood; } public void setHood(String hood) { Hood = hood; } public String getWindshield() { return Windshield; } public void setWindshield(String windshield) { Windshield = windshield; } } 复制代码
抽象的产品建造流程
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/28/21:56 * @Description: 假设车子由以下几个部分组成 用建造者模式模拟汽车的生产 * 抽象车建造者 */ public interface AbstractCarBuild { //创建车的轮子 void createWheel(); //创建车的方向盘 void createsteeringWheel(); //创建车的车盖 void createHood(); //创建车的玻璃 void createWindshield(); //车子创建完成 CarProduct create(); } 复制代码
汽车和卡车具体的建造者
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/28/22:03 * @Description: 具体汽车的建造者 */ public class ConcreteCarBuild1 implements AbstractCarBuild { private CarProduct automobileCar = new CarProduct(); @Override public void createWheel() { automobileCar.setWheel("汽车轮子"); } @Override public void createsteeringWheel() { automobileCar.setSteeringWheel("汽车方向盘"); } @Override public void createHood() { automobileCar.setHood("汽车车盖"); } @Override public void createWindshield() { automobileCar.setWindshield("汽车挡风玻璃"); } @Override public CarProduct create() { return automobileCar; } } 复制代码
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/29/22:51 * @Description:具体货车建造者 */ public class ConcreteCarBuild2 implements AbstractCarBuild{ private CarProduct truckCar = new CarProduct(); @Override public void createWheel() { truckCar.setWheel("货车轮胎"); } @Override public void createsteeringWheel() { truckCar.setSteeringWheel("货车方向盘"); } @Override public void createHood() { truckCar.setHood("货车车盖"); } @Override public void createWindshield() { truckCar.setWindshield("货车挡风玻璃"); } @Override public CarProduct create() { return truckCar; } } 复制代码
定义一个指挥者类负责产品的创建流程:
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/28/22:05 * @Description:指挥者负责产品的创建流程 */ public class CarDirector { private AbstractCarBuild abstractCarBuild; public CarProduct build(){ abstractCarBuild.createHood(); abstractCarBuild.createsteeringWheel(); abstractCarBuild.createWheel(); abstractCarBuild.createWindshield(); return abstractCarBuild.create(); } public CarDirector(AbstractCarBuild abstractCarBuild) { this.abstractCarBuild = abstractCarBuild; } public AbstractCarBuild getAbstractCarBuild() { return abstractCarBuild; } public void setAbstractCarBuild(AbstractCarBuild abstractCarBuild) { this.abstractCarBuild = abstractCarBuild; } } 复制代码
测试代码:
package com.jiangxia.BuilderPattern; /** * @Author: 江夏 * @Date: 2021/10/28/22:07 * @Description: */ public class BuildPatternTest { public static void main(String[] args) { AbstractCarBuild abstractCarBuild = new ConcreteCarBuild1(); CarDirector carDirector = new CarDirector(abstractCarBuild); CarProduct carProduct = carDirector.build(); System.out.println("汽车信息:"); System.out.println(carProduct.getHood()); System.out.println(carProduct.getSteeringWheel()); System.out.println(carProduct.getWheel()); System.out.println(carProduct.getWindshield()); System.out.println("========================"); carDirector.setAbstractCarBuild(new ConcreteCarBuild2()); CarProduct truckProduct = carDirector.build(); System.out.println("货车信息:"); System.out.println(truckProduct.getHood()); System.out.println(truckProduct.getSteeringWheel()); System.out.println(truckProduct.getWheel()); System.out.println(truckProduct.getWindshield()); } } 复制代码
运行结果如下:
通过上述代码的演示,可以总结建造者模式具有以下特点:
优点
1、使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、具体的建造者类之间是相互独立的,对系统的扩展非常有利,有利于系统的解耦。
3、由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。
缺点
1、产品的组成部分必须相同,这限制了其使用范围。
2、如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
应用场景
建造者模式主要适用于以下应用场景:
1、相同的方法,不同的执行顺序,产生不同的结果。
2、多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
3、产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
4、初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
建造者模式和工厂模式的区别
前面介绍了工厂模式从零开始学设计模式(四):工厂模式(Factory Pattern),它们都是创建型设计模式,看起来也很像,那么建造者模式和工厂模式有什么区别呢?
1、建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
2、创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
3、关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
4、建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。