本博客大部分内容来于免费在线学习设计模式
1:生成器模式
生成器模式是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。
2:生成器模式问题
在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。
例如,计算机是由 OPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。
生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。
解决这些问题最简单的方法是扩展基类,然后创建一系列覆盖所有参数组合的子类。但最终你将面对相当数量的子类。任何新增的参数都会让这个层次结构更加复杂。
另一种方法则无需生成子类。你可以在房屋基类中创建一个包括所有可能参数的超级构造函数,并用它来控制房屋对象。这种方法确实可以避免生成子类,但它却会造成另外一个问题:通常情况下,绝大部分的参数都没有使用,这使得对于构造函数的调用十分不简洁。
3:生成器模式解决方案
生成器模式建议将对象构造代码从产品类中抽取出来,并将其放在一个名为生成器的独立对象中。例如将构建一座房屋的过程分解为:创建墙壁,创建房门,创建窗户等。每次创建对象时,你都需要通过生成器对象执行一系列步骤。重点在于你无需调用所有步骤,而只需调用创建特定对象配置所需的那些步骤即可。例如,假设第一个生成器使用木头和玻璃制造房屋,第二个生成器使用石头和钢铁,而第三个生成器使用黄金和钻石。 在调用同一组步骤后,第一个生成器会给你一栋普通房屋,第二个会给你一座小城堡,而第三个则会给你一座宫殿。 但是,只有在调用构造步骤的客户端代码可以通过通用接口与生成器进行交互时,这样的调用才能返回需要的房屋。
主管:你可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类。 主管类可定义创建步骤的执行顺序,而生成器则提供这些步骤的实现。(主管不是必须的,但是主管适合放入各种构造流程,以便在程序中重复调用)。
4:生成器模式结构
- 生成器 (Builder) 接口声明在所有类型生成器中通用的产品构造步骤。
- 具体生成器 (Concrete Builders) 提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。
- 产品 (Products) 是最终生成的对象。 由不同生成器构造的产品无需属于同一类层次结构或接口。
- 主管 (Director) 类定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置。
- 客户端 (Client) 必须将某个生成器对象与主管类关联。 一般情况下,你只需通过主管类构造函数的参数进行一次性关联即可。 此后主管类就能使用生成器对象完成后续所有的构造任务。 但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。 在这种情况下,你在使用主管类生产产品时每次都可以使用不同的生成器。
代码示例: 生成不同类型的汽车产品
1 | // 客户端代码会创建生成器对象并将其传递给主管,然后执行构造过程。最终结果将需要从生成器对象中获取。 |
5:生成器模式适用场景
- 使用生成器模式可避免 “重叠构造函数 (telescopic constructor)” 的出现。
- 当你希望使用代码创建不同形式的产品 (例如跑车和拖拉机) 时,可使用生成器模式。
- 使用生成器构造组合树或其他复杂对象。
6:生成器模式优缺点
优点 | 缺点 |
---|---|
由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。 | 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。 |
生成不同形式的产品时,你可以复用相同的制造代码。 | |
单一职责原则。 你可以将复杂构造代码从产品的业务逻辑中分离出来。 |
工厂模式和生成器模式的区别:
生成器重点关注如何分步生成单个复杂对象。 工厂模式专门用于生产一系列相关对象。 工厂会马上返回产品,生成器则允许你在获取产品前执行一些额外构造步骤。
7:生成器模式与其他模式关系
- 在许多设计工作的初期都会使用工厂方法模式(较为简单,而且可以更方便地通过子类进行定制),随后演化为使用抽象工厂模式、原型模式或生成器模式(更灵活但更加复杂)。
- 生成器重点关注如何分步生成复杂对象。抽象工厂专门用于生产一系列相关对象。抽象工厂会马上返回产品,生成器则允许你在获取产品前执行一些额外构造步骤。
- 你可以在创建复杂组合模式树时使用生成器,因为这可使其构造步骤以递归的方式运行。
- 你可以结合使用生成器和桥接模式:主管类负责抽象工作,各种不同的生成器负责实现工作。
- 抽象工厂、生成器和原型都可以用单例模式来实现。
8:生成器模式举例
想一想,如果不采用组装的方式来做一把椅子,而是每次都从一块整木中制作,将会浪费多少时间或浪费多少资源呢?
生成器就是解决这个问题的。它把一把椅子分成多个组件,根据不同的需要可以设置各个子组件的不同状态,最终这些组件可以组合成一件完整的符合要求的物品。
主管则是家具店,它将各种组件组装好,如果你需要可以直接获取成品,同时也可以根据你的要求对部分组件进行替换,再返回给你一把定制的椅子。