【3W2H设计模式】-建造者模式(Builder Pattern)
一、WHAT 什么建造者模式
**建造者模式(Builder Pattern)**是创建型模式的一种;创建者模式可以将部件与组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到对象,而不需要知道其内部的具体构造细节。
创建者模式:将一个复杂对象的构建与它的表示分离,使得统一的构建过程可以创建不同的表示。
二、WHY 为什么需要建造者模式
创建者模式是针对一些列复杂的对象。在创建过程时,可以抽取共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。
三、WHEN 什么时候用建造者模式
- 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
- 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。
建造者模式是创建复杂的对象,简单对象的创建应该交给工厂方法模式。
工厂模式VS建造者模式
工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。
我们举个简单例子来说明两者的差异,如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后再把内裤外穿,于是一个超人就诞生了。
抽象工厂与建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。
建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。
四、HOW 如何实现建造者模式
4.1、类图
4.2、建造者主要组成与作用
编号 | 组成(角色) | 关系 | 作用 |
1 | 产品类(Product) | 要创建的复杂对象 | |
2 | 抽象建造者类(Builder) | 具体的构建的父类 | 这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。 |
3 | 具体建造者类(Concrete Builder) | 具体构建类 | 实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。 |
4 | 指挥者类(Director) | 按步完成Product的创建 | 调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。 |
5 | 客户调用(Client) | 调用整个创建过程 | 完成创建者模式整个过程 |
4.3、创建者模式具体实现
步骤1、定义产品类(Product)
/** * 产品 */ public class Product { private String partA; private String partB; private String partC; public String getPartA() { return partA; } public void setPartA(String partA) { this.partA = partA; } public String getPartB() { return partB; } public void setPartB(String partB) { this.partB = partB; } public String getPartC() { return partC; } public void setPartC(String partC) { this.partC = partC; } }
步骤2、创建抽象建造者类(Builder)
/** * 创建抽象建造者类(Builder) */ public abstract class Builder { protected Product product= new Product(); public void builderPartA(){} public void builderPartB(){} public void builderPartC(){} public Product createProduct(){ return product; } }
步骤3、创具体建造者类(Concrete Builder)
public class ConcreteBuilder1 extends Builder { @Override public void builderPartA() { System.out.println("ConcreteBuilder1->builderPartA"); } @Override public void builderPartB() { System.out.println("ConcreteBuilder1->builderPartB"); } @Override public void builderPartC() { System.out.println("ConcreteBuilder1->builderPartC"); } }
public class ConcreteBuilder2 extends Builder { @Override public void builderPartA() { System.out.println("ConcreteBuilder2->builderPartA"); } @Override public void builderPartB() { System.out.println("ConcreteBuilder2->builderPartB"); } @Override public void builderPartC() { System.out.println("ConcreteBuilder2->builderPartC"); } }
步骤4、指挥者类(Director)
public class Director { private Builder _builder=null; public Director(Builder builder){ this._builder=builder; } public Product construct(){ _builder.builderPartA(); _builder.builderPartB(); _builder.builderPartC(); return _builder.createProduct(); } }
步骤5、 客户端调用(Client)
public class Client { public static void main(String[] args) { Builder builder1=new ConcreteBuilder1(); show(builder1); Builder builder2=new ConcreteBuilder2(); show(builder2); } private static void show(Builder builder){ Director director=new Director(builder); Product product=director.construct(); product.getPartA(); product.getPartB(); product.getPartC(); } }
五、HOW TO CHANGE(建造者模式如何使用)
5.1、建造者模式的优点
- 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
- 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
5.2、建造者模式的缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
5.2、模式应用
在很多游戏软件中,地图包括天空、地面、背景等组成部分,人物角色包括人体、服装、装备等组成部分,可以使用建造者模式对其进行设计,通过不同的具体建造者创建不同类型的地图或人物。
系统中邮件发送、支付方式选择;