创建类模式对比

Published on 2016 - 09 - 06

创建类模式包括工厂方法模式、建造者模式、抽象工厂模式、单例模式和原型模式,它们都能够提供对象的创建和管理职责。其中的单例模式和原型模式非常容易理解,单例模式是要保持在内存中只有一个对象,原型模式是要求通过复制的方式产生一个新的对象,这两个不容易混淆。剩下的就是工厂方法模式、抽象工厂模式和建造者模式了,这三个之间有较多的相似性。

工厂方法模式VS建造者模式

工厂方法模式注重的是整体对象的创建方法,而建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。我们举个简单例子来说明两者的差异,如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后再把内裤外穿,于是一个超人就诞生了。纯粹使用文字来描述比较枯燥,我们还是通过程序来更加清晰地认识两者的差别。

按工厂方法建造超人

首先,按照工厂方法模式创建出一个超人,类图如图1所示。

类图中我们按照年龄段把超人分为两种类型:成年超人(如克拉克、超能先生)和未成年超人(如Dash、Jack)。这是一个非常正宗的工厂方法模式,定义一个产品的接口,然后再定义两个实现,通过超人制造工厂制造超人。想想看我们对超人最大印象是什么?当然是他的超能力,我们以specialTalent(特殊天赋)方法来代表,先看抽象产品类,如代码清单1所示。

public interface ISuperMan {
     //每个超人都有特殊技能
     public void specialTalent();
}

产品的接口定义好了,我们再来看具体的产品。先看成年超人,很简单,如代码清单2所示。

public class AdultSuperMan implements ISuperMan {
     //超能先生
     public void specialTalent() {
             System.out.println("超人力大无穷");
     }
}

未成年超人的代码如代码清单3所示。

public class ChildSuperMan implements ISuperMan {
     //超能先生的三个孩子
     public void specialTalent() {
             System.out.println("小超人的能力是刀枪不入、快速运动");
     }
}

产品都具备,那我们编写一个工厂类,其意图就是生产超人,具体是成年超人还是未成年超人,则由客户端决定,如代码清单4所示。

public class SuperManFactory {
     //定义一个生产超人的工厂
     public static ISuperMan createSuperMan(String type){
             //根据输入参数产生不同的超人
             if(type.equalsIgnoreCase("adult")){
                     //生产成人超人
                     return new AdultSuperMan();
             }else if(type.equalsIgnoreCase("child")){
                     //生产未成年超人
                     return new ChildSuperMan();
             }else{
                     return null;
             }
     }
}

产品有了,工厂类也有了,剩下的工作就是开始生产超人。这也非常简单,如代码清单5所示。

public class Client {
     //模拟生产超人
     public static void main(String[] args) {
             //生产一个成年超人
             ISuperMan adultSuperMan = SuperManFactory.createSuperMan("adult");
             //展示一下超人的技能
             adultSuperMan.specialTalent();
     }
}

建立了一个超人生产工厂,年复一年地生产超人,对于具体生产出的产品,不管是成年超人还是未成年超人,都是一个模样:深蓝色紧身衣、胸前S标记、内裤外穿,没有特殊的地方。但是我们的目的达到了——生产出超人,拯救全人类,这就是我们的意图。具体怎么生产、怎么组装,这不是工厂方法模式要考虑的,也就是说,工厂模式关注的是一个产品整体,生产出的产品应该具有相似的功能和架构。

注意 通过工厂方法模式生产出对象,然后由客户端进行对象的其他操作,但是并不代表所有生产出的对象都必须具有相同的状态和行为,它是由产品所决定。

按建造者模式建造超人

我们再来看看建造者模式是如何生产超人的,如图2所示。

又是一个典型的建造者模式!哎,不对呀!通用模式上抽象建造者与产品类没有关系呀!是的,我们当然可以加强了,我们在抽象建造者上使用了模板方法模式,每一个建造者都必须返回一个产品,但是产品是如何制造的,则由各个建造者自己负责。我们来看看程序,先看产品类,如代码清单6所示。

public class SuperMan {
     //超人的躯体
     private String body;
     //超人的特殊技能
     private String specialTalent;
     //超人的标志
     private String specialSymbol;
     public String getBody() {
             return body;
     }
     public void setBody(String body) {
             this.body = body;
     }
     public String getSpecialTalent() {
             return specialTalent;
     }
     public void setSpecialTalent(String specialTalent) {
             this.specialTalent = specialTalent;
     }
    public String getSpecialSymbol() {
             return specialSymbol;
     }
     public void setSpecialSymbol(String specialSymbol) {
             this.specialSymbol = specialSymbol;
     }
}

超人这个产品是由三部分组成:躯体、特殊技能、身份标记,这就类似于电子产品,首先生产出一个固件,然后再安装一个灵魂(软件驱动),最后再打上产品标签。完事了!一个崭新的产品就诞生了!我们的超人也是这样生产的,先生产一个普通的躯体,然后注入特殊技能,最后打上S标签,一个超人生产完毕。我们再来看一下建造者的抽象定义,如代码清单7所示。

public abstract class Builder {
     //定义一个超人的应用
     protected final SuperMan superMan = new SuperMan();
     //构建出超人的躯体
     public void setBody(String body){
             this.superMan.setBody(body);
     }
     //构建出超人的特殊技能
     public void setSpecialTalent(String st){
             this.superMan.setSpecialTalent(st);
     }
     //构建出超人的特殊标记
     public void setSpecialSymbol(String ss){
             this.superMan.setSpecialSymbol(ss);
     }
     //构建出一个完整的超人
     public abstract SuperMan getSuperMan();
}

一个典型的模板方法模式,超人的各个部件(躯体、灵魂、标志)都准备好了,具体怎么组装则是由实现类来决定。我们先来看成年超人,如代码清单8所示。

public class AdultSuperManBuilder extends Builder {
     @Override
     public SuperMan getSuperMan() {
             super.setBody("强壮的躯体");
             super.setSpecialTalent("会飞行");
             super.setSpecialSymbol("胸前带S标记");
             return super.superMan;
     }
}

怎么回事?在之前讲解建造者模式的时候在产品中使用了模板方法模式,在这里怎么把模板方法模式迁移到建造者了?怎么会这样?你是不是在发出这样的疑问?别疑问了!设计模式只是提供了一个解决问题的意图:复杂对象的构建与它的表示分离,而没有具体定出一个设计模式必须是这样的实现,必须是这样的代码,灵活运用模式才是其根本,别学死板了。

我们继续看未成年超人的建造者,如代码清单9所示。

public class ChildSuperManBuilder extends Builder {
     @Override
     public SuperMan getSuperMan() {
             super.setBody("强壮的躯体");
             super.setSpecialTalent("刀枪不入");
            super.setSpecialSymbol("胸前带小S标记");
             return super.superMan;
     }
}

大家注意看我们这两个具体的建造者,它们都关注了产品的各个部分,在某些应用场景下甚至会关心产品的构建顺序,即使是相同的部件,装配顺序不同,产生的结果也不同,这也正是建造者模式的意图:通过不同的部件、不同装配产生不同的复杂对象。我们再来看导演类,如代码清单10所示。

public class Director {
     //两个建造者的应用
     private static Builder  adultBuilder = new AdultSuperManBuilder();
     //未成年超人的建造者
     private static Builder childBuilder = new ChildSuperManBuilder();
     //建造一个成年、会飞行的超人
    public static SuperMan getAdultSuperMan(){
             return adultBuilder.getSuperMan();
     }
     //建造一个未成年、刀枪不入的超人
     public static SuperMan getChildSuperMan(){
             return childBuilder.getSuperMan();
     }
}

这很简单,不多说了!看看场景类是如何调用的,如代码清单11所示。

public class Client {
     public static void main(String[] args) {
             //建造一个成年超人
             SuperMan adultSuperMan = Director.getAdultSuperMan();
             //展示一下超人的信息
             adultSuperMan.getSpecialTalent();
     }
}

这个场景类的写法与工厂方法模式是相同的,但是你可以看到,在建立超人的过程中,建造者必须关注超人的各个部件,而工厂方法模式则只关注超人的整体,这就是两者的区别。

最佳实践

工厂方法模式和建造者模式都属于对象创建类模式,都用来创建类的对象。但它们之间的区别还是比较明显的。

  • 意图不同

在工厂方法模式里,我们关注的是一个产品整体,如超人整体,无须关心产品的各部分是如何创建出来的;但在建造者模式中,一个具体产品的产生是依赖各个部件的产生以及装配顺序,它关注的是“由零件一步一步地组装出产品对象”。简单地说,工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程。

  • 产品的复杂度不同

工厂方法模式创建的产品一般都是单一性质产品,如成年超人,都是一个模样,而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象当然不同。这不是说工厂方法模式创建的对象简单,而是指它们的粒度大小不同。一般来说,工厂方法模式的对象粒度比较粗,建造者模式的产品对象粒度比较细。

两者的区别有了,那在具体的应用中,我们该如何选择呢?是用工厂方法模式来创建对象,还是用建造者模式来创建对象,这完全取决于我们在做系统设计时的意图,如果需要详细关注一个产品部件的生产、安装步骤,则选择建造者,否则选择工厂方法模式。

抽象工厂模式VS建造者模式

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品,两者的区别还是比较明显的,但是还有读者对这两个模式产生混淆,我们通过一个例子说明两者的差别。

现代化的汽车工厂能够批量生产汽车(不考虑手工打造的豪华车)。不同的工厂生产不同的汽车,宝马工厂生产宝马牌子的车,奔驰工厂生产奔驰牌子的车。车不仅具有不同品牌,还有不同的用途分类,如商务车Van,运动型车SUV等,我们按照两种设计模式分别实现车辆的生产过程。

按抽象工厂模式生产车辆

按照抽象工厂模式,首先需要定义一个抽象的产品接口即汽车接口,然后宝马和奔驰分别实现该接口,由于它们只具有了一个品牌属性,还没有定义一个具体的型号,属于对象的抽象层次,每个具体车型由其子类实现,如R系列的奔驰车是商务车,X系列的宝马车属于SUV,我们来看类图,如图3所示。

在类图中,产品类很简单,我们从两个维度看产品:品牌和车型,每个品牌下都有两个车型,如宝马SUV,宝马商务车等,同时我们又建造了两个工厂,一个专门生产宝马车的宝马工厂BMWFactory,一个是生产奔驰车的奔驰车生产工厂BenzFactory。当然,汽车工厂也有两个不同的维度,可以建立这样两个工厂:一个专门生产SUV车辆的生产工厂,生产宝马SUV和奔驰SUV,另外一个工厂专门生成商务车,分别是宝马商务车和奔驰商务车,这样设计在技术上是完全可行的,但是在业务上是不可行的,为什么?这是因为你看到过有一个工厂既能生产奔驰SUV也能生产宝马SUV吗?这是不可能的,因为业务受限,除非是国内的山寨工厂。我们先来看产品类,汽车接口如代码清单12所示。

public interface ICar {
     //汽车的生产商,也就是牌子
     public String getBand();
     //汽车的型号
     public String getModel();
}

在产品接口中我们定义了车辆有两个可以查询的属性:品牌和型号,奔驰车和宝马车是两个不同品牌的产品,但不够具体,只是知道它们的品牌而已,还不能够实例化,因此还是一个抽象类,如代码清单13所示。

public abstract class AbsBMW implements ICar {
     private final static String BMW_BAND = "宝马汽车";
     //宝马车
     public String getBand() {
             return BMW_BAND;
     }
     //型号由具体的实现类实现
     public abstract String getModel();
}

抽象产品类中实现了产品的类型定义,车辆的型号没有实现,两实现类分别实现商务车和运动型车,分别如代码清单14、代码清单15所示。

public class BMWVan extends AbsBMW {
     private final static String SEVENT_SEARIES = "7系列车型商务车";
     public String getModel() {
             return SEVENT_SEARIES;
     }
}
public class BMWSuv extends AbsBMW {
     private final static String X_SEARIES = "X系列车型SUV";
     public String getModel() {
             return X_SEARIES;
     }
}

奔驰车与宝马车类似,都已经有清晰品牌定义,但是型号还没有确认,也是一个抽象的产品类,如代码清单16所示。

public abstract class AbsBenz implements ICar {
     private final static String BENZ_BAND = "奔驰汽车";
     public String getBand() {
             return BENZ_BAND;
     }
     //具体型号由实现类完成
     public abstract String getModel();
}

由于分类的标准是相同的,因此奔驰车也应该有商务车和运动车两个类型,分别如代码清单17和代码清单18所示。

public class BenzVan extends AbsBenz {
     private final static String R_SERIES = "R系列商务车";
     public String getModel() {
             return R_SERIES;
     }
}
public class BenzSuv extends AbsBenz {
     private final static String G_SERIES = "G系列SUV";
     public String getModel() {
             return G_SERIES;
     }
}

所有的产品类都已经实现了,剩下的工作就是要定义工厂类进行生产,由于产品类型多样,也导致了必须有多个工厂类来生产不同产品,首先就需要定义一个抽象工厂,声明每个工厂必须完成的职责,如代码清单19所示。

public interface CarFactory {
     //生产SUV
     public ICar createSuv();
     //生产商务车
     public ICar createVan();
}

抽象工厂定义了每个工厂必须生产两个类型车:SUV(运动车)和VAN(商务车),否则一个工厂就不能被实例化,我们来看宝马车工厂,如代码清单20所示。

public class BMWFactory implements CarFactory {
     //生产SUV
     public ICar createSuv() {
             return new BMWSuv();
     }
     //生产商务车
     public ICar createVan(){
             return new BMWVan();
     }
}

很简单,你要我生产宝马商务车,没问题,直接产生一个宝马商务车对象,返回给调用者,这对调用者来说根本不需要关心到底是怎么生产的,它只要找到一个宝马工厂,即可生产出自己需要的产品(汽车)。奔驰车工厂与此类似,如代码清单21所示。

public class BenzFactory implements CarFactory {
     //生产SUV
     public ICar createSuv() {
             return new BenzSuv();
     }
     //生产商务车
     public ICar createVan(){
             return new BenzVan();
     }
}

产品和工厂都具备了,剩下的工作就是建立一个场景类模拟调用者调用,如代码清单22所示。

public class Client {
     public static void main(String[] args) {
             //要求生产一辆奔驰SUV
             System.out.println("===要求生产一辆奔驰SUV===");
             //首先找到生产奔驰车的工厂
             System.out.println("A、找到奔驰车工厂");
             CarFactory carFactory= new BenzFactory();
             //开始生产奔驰SUV
             System.out.println("B、开始生产奔驰SUV");
             ICar benzSuv = carFactory.createSuv();
             //生产完毕,展示一下车辆信息
             System.out.println("C、生产出的汽车如下:");
             System.out.println("汽车品牌:"+benzSuv.getBand());
             System.out.println("汽车型号:" + benzSuv.getModel());
     }
}

运行结果如下所示:

===要求生产一辆奔驰SUV===
A、找到奔驰车工厂
B、开始生产奔驰SUV
C、生产出的汽车如下:
汽车品牌:奔驰汽车
汽车型号:G系列SUV

对外界调用者来说,只要更换一个具备相同结构的对象,即可发生非常大的改变,如我们原本使用BenzFactory生产汽车,但是过了一段时间后,我们的系统需要生产宝马汽车,这对系统来说不需要很大的改动,只要把工厂类使用BMWFactory代替即可,立刻可以生产出宝马车,注意这里生产的是一辆完整的车,对于一个产品,只要给出产品代码(车类型)即可生产,抽象工厂模式把一辆车认为是一个完整的、不可拆分的对象。它注重完整性,一个产品一旦找到一个工厂生产,那就是固定的型号,不会出现一个宝马工厂生产奔驰车的情况。那现在的问题是我们就想要一辆混合的车型,如奔驰的引擎,宝马的车轮,那该怎么处理呢?使用我们的建造者模式!

按建造者模式生产车辆

按照建造者模式设计一个生产车辆需要把车辆进行拆分,拆分成引擎和车轮两部分,然后由建造者进行建造,想要什么车,你只要有设计图纸就成,马上可以制造一辆车出来。它注重的是对零件的装配、组合、封装,它从一个细微构件装配角度看待一个对象。我们来看生产车辆的类图,如图4所示。

注意看我们类图中的蓝图类Blueprint,它负责对产品建造过程定义。既然要生产产品,那必然要对产品进行一个描述,在类图中我们定义了一个接口来描述汽车,如代码清单23所示。

public interface ICar {
     //汽车车轮
     public String getWheel();
     //汽车引擎
     public String getEngine();
}

我们定义一辆车必须有车轮和引擎,具体的产品如代码清单24所示。

public class Car implements ICar {
     //汽车引擎
     private String engine;
     //汽车车轮
     private String wheel;
     //一次性传递汽车需要的信息
     public Car(String _engine,String _wheel){
             this.engine = _engine;
             this.wheel = _wheel;
     }
     public String getEngine() {
             return engine;
     }
     public String getWheel() {
             return wheel;
     }
     public String toString(){
             return "车的轮子是:" + wheel + "\n车的引擎是:" + engine;
     }
}

一个简单的JavaBean定义产品的属性,明确对产品的描述。我们继续来思考,因为我们的产品是比较抽象的,它没有指定引擎的型号,也没有指定车轮的牌子,那么这样的组合方式有很多,完全要靠建造者来建造,建造者说要生产一辆奔驰SUV那就得用奔驰的引擎和奔驰的车轮,该建造者对于一个具体的产品来说是绝对的权威,我们来描述一下建造者,如代码清单25所示。

public abstract class CarBuilder {
     //待建造的汽车
     private ICar car;
     //设计蓝图
     private Blueprint bp;
     public Car buildCar(){
             //按照顺序生产一辆车
             return new Car(buildEngine(),buildWheel());
     }
     //接收一份设计蓝图
     public void receiveBlueprint(Blueprint _bp){
             this.bp = _bp;
     }
     //查看蓝图,只有真正的建造者才可以查看蓝图
     protected Blueprint getBlueprint(){
             return bp;
     }
     //建造车轮
     protected abstract String buildWheel();
     //建造引擎
     protected abstract String buildEngine();
}

看到Blueprint类了,它中文的意思是“蓝图”,你要建造一辆车必须有一个设计样稿或者蓝图吧,否则怎么生产?怎么装配?该类就是一个可参考的生产样本,如代码清单26所示。

public class Blueprint {
     //车轮的要求
     private String wheel;
     //引擎的要求
    private String engine;
     public String getWheel() {
             return wheel;
     }
     public void setWheel(String wheel) {
             this.wheel = wheel;
     }
     public String getEngine() {
             return engine;
     }
     public void setEngine(String engine) {
             this.engine = engine;
     }     
}

这和一个具体的产品Car类是一样的?错,不一样!它是一个蓝图,是一个可以参考的模板,有一个蓝图可以设计出非常多的产品,如有一个R系统的奔驰商务车设计蓝图,我们就可以生产出一系列的奔驰车。它指导我们的产品生产,而不是一个具体的产品。我们来看宝马车建造车间,如代码清单27所示。

public class BMWBuilder extends CarBuilder {
     public String buildEngine() {
             return super.getBlueprint().getEngine();
     }
     public String buildWheel() {
             return super.getBlueprint().getWheel();
     }
}

这是非常简单的类。只要获得一个蓝图,然后按照蓝图制造引擎和车轮即可,剩下的事情就交给抽象的建造者进行装配。奔驰车间与此类似,如代码清单28所示。

public class BenzBuilder extends CarBuilder {
     public String buildEngine() {
             return super.getBlueprint().getEngine();
     }
     public String buildWheel() {
             return super.getBlueprint().getWheel();
     }
}

两个建造车间都已经完成,那现在的问题就变成了怎么让车间运作,谁来编写蓝图?谁来协调生产车间?谁来对外提供最终产品?于是导演类出场了,它不仅仅有每个车间需要的设计蓝图,还具有指导不同车间装配顺序的职责,如代码清单29所示。

public class Director {
     //声明对建造者的引用
     private CarBuilder benzBuilder = new BenzBuilder();
     private CarBuilder bmwBuilder = new BMWBuilder();
     //生产奔驰SUV
     public ICar createBenzSuv(){
             //制造出汽车
             return createCar(benzBuilder, "benz的引擎", "benz的轮胎");
     }
     //生产出一辆宝马商务车
     public ICar createBMWVan(){
             return createCar(benzBuilder, "BMW的引擎", "BMW的轮胎");
     }
     //生产出一个混合车型
     public ICar createComplexCar(){          
             return createCar(bmwBuilder, "BMW的引擎", "benz的轮胎");
     }
     //生产车辆
     private ICar createCar(CarBuilder _carBuilder,String engine,String wheel){
             //导演怀揣蓝图
             Blueprint bp = new Blueprint();
             bp.setEngine(engine);
             bp.setWheel(wheel);
             System.out.println("获得生产蓝图");
             _carBuilder.receiveBlueprint(bp);
             return _carBuilder.buildCar();
     }
}

这里有一个私有方法createCar,其作用是减少导演类中的方法对蓝图的依赖,全部由该方法来完成。我们编写一个场景类,如代码清单30所示。

public class Client {
     public static void main(String[] args) {
             //定义出导演类
             Director director =new Director();
             //给我一辆奔驰车SUV
             System.out.println("===制造一辆奔驰SUV===");
             ICar benzSuv = director.createBenzSuv();
             System.out.println(benzSuv);
             //给我一辆宝马商务车
             System.out.println("\n===制造一辆宝马商务车===");
             ICar bmwVan = director.createBMWVan();
             System.out.println(bmwVan);
             //给我一辆混合车型
             System.out.println("\n===制造一辆混合车===");
             ICar complexCar = director.createComplexCar();
             System.out.println(complexCar);
     }
}

场景类只要找到导演类(也就是车间主任了)说给我制造一辆这样的宝马车,车间主任马上通晓你的意图,设计了一个蓝图,然后命令建造车间拼命加班加点建造,最终返回给你一件最新出品的产品,运行结果如下所示:

===制造一辆奔驰SUV===
获得生产蓝图
车的轮子是:benz的轮胎
车的引擎是:benz的引擎
===制造一辆宝马商务车===
获得生产蓝图
车的轮子是:BMW的轮胎
车的引擎是:BMW的引擎
===制造一辆混合车===
获得生产蓝图
车的轮子是:benz的轮胎
车的引擎是:BMW的引擎

注意最后一个运行结果片段,我们可以立刻生产出一辆混合车型,只要有设计蓝图,这非常容易实现。反观我们的抽象工厂模式,它是不可能实现该功能的,因为它更关注的是整体,而不关注到底用的是奔驰引擎还是宝马引擎,而我们的建造者模式却可以很容易地实现该设计,市场信息变更了,我们就可以立刻跟进,生产出客户需要的产品。

最佳实践

注意看上面的描述,我们在抽象工厂模式中使用“工厂”来描述构建者,而在建造者模式中使用“车间”来描述构建者,其实我们已经在说它们两者的区别了,抽象工厂模式就好比是一个一个的工厂,宝马车工厂生产宝马SUV和宝马VAN,奔驰车工厂生产奔驰车SUV和奔驰VAN,它是从一个更高层次去看对象的构建,具体到工厂内部还有很多的车间,如制造引擎的车间、装配引擎的车间等,但这些都是隐藏在工厂内部的细节,对外不公布。也就是对领导者来说,他只要关心一个工厂到底是生产什么产品的,不用关心具体怎么生产。而建造者模式就不同了,它是由车间组成,不同的车间完成不同的创建和装配任务,一个完整的汽车生产过程需要引擎制造车间、引擎装配车间的配合才能完成,它们配合的基础就是设计蓝图,而这个蓝图是掌握在车间主任(导演类)手中,它给建造车间什么蓝图就能生产什么产品,建造者模式更关心建造过程。虽然从外界看来一个车间还是生产车辆,但是这个车间的转型是非常快的,只要重新设计一个蓝图,即可产生不同的产品,这有赖于建造者模式的功劳。

相对来说,抽象工厂模式比建造者模式的尺度要大,它关注产品整体,而建造者模式关注构建过程,因此建造者模式可以很容易地构建出一个崭新的产品,只要导演类能够提供具体的工艺流程。也正因为如此,两者的应用场景截然不同,如果希望屏蔽对象的创建过程,只提供一个封装良好的对象,则可以选择抽象工厂方法模式。而建造者模式可以用在构件的装配方面,如通过装配不同的组件或者相同组件的不同顺序,可以产生出一个新的对象,它可以产生一个非常灵活的架构,方便地扩展和维护系统。

参考文档