8.2 解 决 方 案

8.2.1 使用生成器模式来解决问题

用来解决上述问题的一个合理的解决方案就是生成器模式。那么什么是生成器模式呢?

1.生成器模式的定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

2.应用生成器模式来解决问题的思路

仔细分析上面的实现,构建每种格式的数据文件的处理过程,这不就是构建过程吗?而每种格式具体的步骤实现,不就相当于是不同的表示吗?因为不同的步骤实现,决定了最终的表现也就不同。也就是说,上面的问题恰好就是生成器模式要解决的问题。

要实现同样的构建过程可以创建不同的表现,那么一个自然的思路就是先把构建过程独立出来,在生成器模式中把它称为指导者,由它来指导装配过程,但是不负责每步具体的实现。当然,光有指导者是不够的,必须要有能具体实现每步的对象,在生成器模式中称这些实现对象为生成器。

这样一来,指导者就是可以重用的构建过程,而生成器是可以被切换的具体实现。前面的实现中,每种具体的导出文件格式的实现就相当于生成器。

8.2.2 生成器模式的结构和说明

生成器模式的结构如图8.1所示。

图片

图8.1 生成器模式结构示意图

■ Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。

■ ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。

■ Director:指导者,也被称为导向者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象。

■ Product:产品,表示被生成器构建的复杂对象,包含多个部件。

8.2.3 生成器模式示例代码

(1)生成器接口定义的示例代码如下:

4d6e2dc3d3d44f4b9be51bf544a569a7

(2)具体生成器实现的示例代码如下:

a3e4f83495e845b1b5996348fe8e8cfd

(3)相应的产品对象接口的示例代码如下:

1be85efdf20743468295821071f6f9f6

(4)最后来看看指导者的实现示意。示例代码如下:

bd85c951c76c4302a342d092ec435848

65d4032d8b344121a4173d7e8634de28

8.2.4 使用生成器模式重写示例

要使用生成器模式来重写示例,重要的任务就是要把指导者和生成器接口定义出来。指导者就是用来执行那四个步骤的对象,而生成器是用来实现每种格式下,对于每个步骤的具体实现的对象。

按照生成器模式重写示例的结构如图8.2所示。

图片

图8.2 生成器模式重写示例的结构示意图

下面还是一起来看看代码,会比较清楚。

(1)前面示例中的三个数据模型对象还继续沿用,这里就不再赘述了。

(2)下面来看看定义的Builder接口,主要是把导出各种格式文件的处理过程的步骤定义出来,每个步骤负责构建最终导出文件的一部分。示例代码如下:

9c013b2b416f4988a8f7b4fcebe274a9

(3)接下来看看具体的生成器实现。其实就是把原来示例中写在一起的实现,拆分成多个步骤实现。

先来看导出数据到文本文件的生成器实现。示例代码如下:

ec4d1d0c477b4914a8a7b2860b19a8e5

4c99f9efe2d34f6c91a3750026ff6b18

再看看导出数据到XML文件的生成器实现。示例代码如下:

8a8f4bcdd0854d4ab7dd6151fb4aaf1a

e0bcaa7cd0134cc88e4af5ab0248c4b2

2a4b0899154d4dadbe227a4266f7dc4f

(4)指导者。有了具体的生成器实现后,需要由指导者来指导它进行具体的产品构建。由于构建的产品是文本内容,所以就不用单独定义产品对象了。示例代码如下:

27f6b4e6facf4902991699460f1f72f2

060719ea274948de9acf80c8a2e28647

d593751a15da487780d0dbf4843314fb

(5)都实现得差不多了,下面编写客户端程序测试一下。示例代码如下:

0acd607d716547388a63c4c336ca268f

16de91db508a434b98dc5cb33f12f647

a69cb4695dff43408ccaec3367d1b98f

43481bce66894eadb9b7b28573d06161

看了上面的示例会发现,其实生成器模式也挺简单的,好好体会一下。通过上面的讲述,应该能很清晰地看出生成器模式的实现方式和它的优势所在了,那就是对同一个构建过程,只要配置不同的生成器实现,就会生成不同表现的对象。