设计模式之生成器模式
作者:Aaron
来源:SegmentFault 思否社区
生成器模式又叫做建造者模式,之前介绍的一些创建型的设计模式基本都比较简单的,生成器模式是较为复杂的创建型模式,它将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。
它关注如何一步一步创建一个的复杂对象,不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,增加新的建造者非常方便,无须修改已有代码,系统具有较好的拓展性。
生成器模式:是一种设计模式,又名:建造模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。—— 节选自维基百科
例如,我们来思考如何创建一辆汽车对象。创造一辆简单的汽车,首先需要创建车的框架和车轱辘,然后安装汽车门、汽车玻璃,最后再安装上发动机。但是如果你想要一个性能更好的汽车的话,那么还需要给汽车加上一些其他的设施,这个时候咱们需要怎么去做呢?
最简单的方法是拓展原有汽车的基类,然后创建一系列涵盖所有参数组合的子类。但最终将面对相当数量的子类。任何新增的参数都会让这个层次结构更加复杂。
另一种方法则无需生成子类。可以再汽车的基类中创建一个包括所有可能参数的超级构造函数,并用它来控制汽车对象。这种方法可以避免生成子类,但它却会造成另外一个问题。通常情况下,绝大部分的参数都没有使用,这使得对于构造函数的调用十分不简洁。
生成器模式优缺点
生成器模式会将对象构造过程划分为一组步骤,每次创建对象时,你都需要通过生成器对象执行一系列步骤。重点在于你无需调用所有步骤,而只需调用创建特定对象配置所需的那些步骤即可。当你需要创建不同形式的产品时,其中的一些构造步骤可能需要不同的实现。可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。然后你就可以在创建过程中使用这些生成器 (例如按顺序调用多个构造步骤) 来生成不同类型的对象。
优点
在生成器模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合开闭原则 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
生成器模式所生成的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本
生成器:接口生命再所有类型生成器中通用的产品构造步骤 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口 指挥者:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
// 抽象建造者
abstract class Builder {
public abstract buildPartA():void;
public abstract buildPartB():void;
public abstract buildPartC():void;
public abstract buildProduct():Product;
}
// 具体建造者
class ConcreteBuilder extends Builder {
private product:Product;
constructor(product:Product) {
super();
this.product = product;
}
public buildPartA():void {}
public buildPartB():void {}
public buildPartC():void {}
// 最终组建一个产品
public buildProduct():Product {
return this.product;
}
}
// 产品角色
class Product {
public doSomething():void {
// 独立业务
}
}
// 指挥者
class Director {
private _builder:Builder;
constructor(builder:Builder) {
this._builder = builder;
}
set builder(builder:Builder) {
this._builder = builder;
}
// 将处理建造的流程交给指挥者
public constructorProduct() {
this._builder.buildPartA();
this._builder.buildPartB();
this._builder.buildPartC();
return this._builder.buildProduct();
}
}
// 使用
const builder:Builder = new ConcreteBuilder(new Product());
const director:Director = new Director(builder);
const product:Product = director.constructorProduct();