生成器模式
1 简介
生成器模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
这句话怎么理解呢?
我们来把一些关键词逐一解释下:
复杂对象:通常是指含有多个部件,且需要按某种步骤将各部件组合在一起的对象。
对象的构建:指将各部件按某种步骤组合成一个对象的过程。
对象的表示:指各部件的具体实现。
2 模拟场景
我们还是举生产电脑的例子。
这个例子的具体场景和工厂类方法中生产电脑的场景不太一样。(如果想详细了解工厂类方法中的场景,请自行查看工厂类方法对应的章节)
在工厂类方法中,我们关注的是如何创建电脑的单个部件或者相互依赖的几个部件。但我们都知道,仅有电脑的部件还不行,还需要将各部件组合起来才能形成一台完整的电脑。这就是生成器模式所说的“复杂对象的构建”。
我们再考虑下,一家电脑厂商通常会生产不同型号的电脑,比如高性能电脑、低成本电脑。
生产不同型号的电脑的过程有如下特点:
组装过程一样,都是先有主板,然后把CPU、内存条、硬盘安装到主板上。即:同样的构建过程。
采用的硬盘、内存条、CPU、主板不一样。即:不同的表示。
这就可以采用生成器模式“同样的构建过程可以创建不同的表示”的特点来实现。
3 使用生成器模式实现电脑对象的创建
参与者
- Product: Computer
定义电脑(被创建的复杂对象)的接口
- Builder: ComputerBuilder
指定创建Computer的各部件的接口----BuildHardDisk()、BuildDdr()、BuildCpu()、BuildBoard()
指定返回Computer的接口----GetComputer()
- ConcreteBuilder: HighPerfComputerBuilder、LowCostComputerBuilder
实现ComputerBuilder接口
- Director: ComputerDirector
使用ComputerBuilder接口,指定Computer的构建步骤。即:提供一个Construct()方法,该方法调用ComputerBuilder的接口,按步骤创建Computer。
UML
Computer示例代码
computer.h
#ifndef COMPUTER_H
#define COMPUTER_H
struct Computer {
char hardDisk[30];
char ddr[30];
char cpu[30];
char board[30];
void (*SetHardDisk)(struct Computer *this, char *hardDisk);
void (*SetDdr)(struct Computer *this, char *ddr);
void (*SetCpu)(struct Computer *this, char *cpu);
void (*SetBoard)(struct Computer *this, char *board);
void (*Show)(struct Computer *this);
};
// 构造函数
void Computer(struct Computer *this);
// 析构函数
void _Computer(struct Computer *this);
#endif
computer.c
#include <stdio.h>
#include <string.h>
#include "computer.h"
static void SetHardDisk(struct Computer *this, char *hardDisk)
{
strncpy(this->hardDisk, hardDisk, 30);
this->hardDisk[30 - 1] = '\0';
}
static void SetDdr(struct Computer *this, char *ddr)
{
strncpy(this->ddr, ddr, 30);
this->ddr[30 - 1] = '\0';
}
static void SetCpu(struct Computer *this, char *cpu)
{
strncpy(this->cpu, cpu, 30);
this->cpu[30 - 1] = '\0';
}
static void SetBoard(struct Computer *this, char *board)
{
strncpy(this->board, board, 30);
this->cpu[30 - 1] = '\0';
}
static void Show(struct Computer *this)
{
printf("输出电脑对象:\n");
printf(" %s\n", this->board);
printf(" %s\n", this->cpu);
printf(" %s\n", this->ddr);
printf(" %s\n", this->hardDisk);
}
void Computer(struct Computer *this)
{
this->hardDisk[0] = '\0';
this->ddr[0] = '\0';
this->cpu[0] = '\0';
this->board[0] = '\0';
this->SetHardDisk = SetHardDisk;
this->SetDdr = SetDdr;
this->SetCpu = SetCpu;
this->SetBoard = SetBoard;
this->Show = Show;
}
void _Computer(struct Computer *this)
{
this->SetHardDisk = NULL;
this->SetDdr = NULL;
this->SetCpu = NULL;
this->SetBoard = NULL;
this->Show = NULL;
}
ComputerBuilder示例代码
computer_builder.h
#ifndef COMPUTER_BUILDER_H
#define COMPUTER_BUILDER_H
#include "computer.h"
struct ComputerBuilder {
struct Computer *computer;
void (*BuildHardDisk)(struct ComputerBuilder *this);
void (*BuildDdr)(struct ComputerBuilder *this);
void (*BuildCpu)(struct ComputerBuilder *this);
void (*BuildBoard)(struct ComputerBuilder *this);
struct Computer* (*GetComputer)(struct ComputerBuilder *this);
};
#endif
HighPerfComputerBuilder示例代码
high_perf_computer_builder.h
#ifndef HIGH_PERF_COMPUTER_BUILDER_H
#define HIGH_PERF_COMPUTER_BUILDER_H
#include "computer_builder.h"
struct HighPerfComputerBuilder {
struct ComputerBuilder computerBuilder;
};
// 构造函数
void HighPerfComputerBuilder(struct HighPerfComputerBuilder *this);
// 析构函数
void _HighPerfComputerBuilder(struct HighPerfComputerBuilder *this);
#endif
high_perf_computer_builder.c
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "high_perf_computer_builder.h"
static void BuildHardDisk(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetHardDisk(this->computer, "2T大容量硬盘");
}
static void BuildDdr(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetDdr(this->computer, "32G内存");
}
static void BuildCpu(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetCpu(this->computer, "i7八核八线程CPU");
}
static void BuildBoard(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetBoard(this->computer, "高端主板");
}
static struct Computer* GetComputer(struct ComputerBuilder *this) {
return this->computer;
}
void HighPerfComputerBuilder(struct HighPerfComputerBuilder *this)
{
this->computerBuilder.computer = malloc(sizeof(struct Computer));
Computer(this->computerBuilder.computer);
this->computerBuilder.BuildHardDisk = BuildHardDisk;
this->computerBuilder.BuildDdr = BuildDdr;
this->computerBuilder.BuildCpu = BuildCpu;
this->computerBuilder.BuildBoard = BuildBoard;
this->computerBuilder.GetComputer = GetComputer;
}
void _HighPerfComputerBuilder(struct HighPerfComputerBuilder *this)
{
if (this->computerBuilder.computer != NULL) {
_Computer(this->computerBuilder.computer);
free(this->computerBuilder.computer);
this->computerBuilder.computer = NULL;
}
this->computerBuilder.BuildHardDisk = NULL;
this->computerBuilder.BuildDdr = NULL;
this->computerBuilder.BuildCpu = NULL;
this->computerBuilder.BuildBoard = NULL;
this->computerBuilder.GetComputer = NULL;
}
LowCostComputerBuilder示例代码
low_cost_computer_builder.h
#ifndef LOW_COST_COMPUTER_BUILDER_H
#define LOW_COST_COMPUTER_BUILDER_H
#include "computer_builder.h"
struct LowCostComputerBuilder {
struct ComputerBuilder computerBuilder;
};
// 构造函数
void LowCostComputerBuilder(struct LowCostComputerBuilder *this);
// 析构函数
void _LowCostComputerBuilder(struct LowCostComputerBuilder *this);
#endif
low_cost_computer_builder.c
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "low_cost_computer_builder.h"
static void BuildHardDisk(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetHardDisk(this->computer, "256G硬盘");
}
static void BuildDdr(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetDdr(this->computer, "4G内存");
}
static void BuildCpu(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetCpu(this->computer, "i3CPU");
}
static void BuildBoard(struct ComputerBuilder *this)
{
if (this->computer == NULL) {
printf("err: computer is null\n");
}
this->computer->SetBoard(this->computer, "普通主板");
}
static struct Computer* GetComputer(struct ComputerBuilder *this) {
return this->computer;
}
void LowCostComputerBuilder(struct LowCostComputerBuilder *this)
{
this->computerBuilder.computer = malloc(sizeof(struct Computer));
Computer(this->computerBuilder.computer);
this->computerBuilder.BuildHardDisk = BuildHardDisk;
this->computerBuilder.BuildDdr = BuildDdr;
this->computerBuilder.BuildCpu = BuildCpu;
this->computerBuilder.BuildBoard = BuildBoard;
this->computerBuilder.GetComputer = GetComputer;
}
void _LowCostComputerBuilder(struct LowCostComputerBuilder *this)
{
if (this->computerBuilder.computer != NULL) {
_Computer(this->computerBuilder.computer);
free(this->computerBuilder.computer);
this->computerBuilder.computer = NULL;
}
this->computerBuilder.BuildHardDisk = NULL;
this->computerBuilder.BuildDdr = NULL;
this->computerBuilder.BuildCpu = NULL;
this->computerBuilder.BuildBoard = NULL;
this->computerBuilder.GetComputer = NULL;
}
ComputerDirector示例代码
computer_director.h
#ifndef COMPUTER_DIRECTOR_H
#define COMPUTER_DIRECTOR_H
#include "computer_builder.h"
struct ComputerDirector {
void (*Construct)(struct ComputerDirector *this, struct ComputerBuilder *computerBuilder);
};
// 构造函数
void ComputerDirector(struct ComputerDirector *this);
// 析构函数
void _ComputerDirector(struct ComputerDirector *this);
#endif
computer_director.c
#include <stdio.h>
#include "computer_director.h"
void Construct(struct ComputerDirector *this, struct ComputerBuilder *computerBuilder)
{
printf("开始构建电脑\n");
printf(" 第一步:创建主板\n");
computerBuilder->BuildBoard(computerBuilder);
printf(" 第二步:在主板上安装CPU\n");
computerBuilder->BuildCpu(computerBuilder);
printf(" 第三步:在主板上安装内存条\n");
computerBuilder->BuildDdr(computerBuilder);
printf(" 第四步:在主板上安装硬盘\n");
computerBuilder->BuildHardDisk(computerBuilder);
}
void ComputerDirector(struct ComputerDirector *this)
{
this->Construct = Construct;
}
void _ComputerDirector(struct ComputerDirector *this)
{
this->Construct = NULL;
}
客户端代码示例
main.c
#include <stddef.h>
#include <stdio.h>
#include "computer_director.h"
#include "high_perf_computer_builder.h"
#include "low_cost_computer_builder.h"
void main()
{
struct Computer *computer = NULL;
struct ComputerDirector computerDirector;
ComputerDirector(&computerDirector);
// 构建高性能电脑
printf("构建高性能电脑\n");
struct HighPerfComputerBuilder highPerfComputerBuilder;
HighPerfComputerBuilder(&highPerfComputerBuilder);
computerDirector.Construct(&computerDirector, (struct ComputerBuilder*)&highPerfComputerBuilder);
computer = highPerfComputerBuilder.computerBuilder.GetComputer((struct ComputerBuilder*)&highPerfComputerBuilder);
if (computer != NULL) {
computer->Show(computer);
}
_HighPerfComputerBuilder(&highPerfComputerBuilder);
printf("\n\n");
// 构建低成本电脑
printf("构建低成本电脑\n");
struct LowCostComputerBuilder lowCostComputerBuilder;
LowCostComputerBuilder(&lowCostComputerBuilder);
computerDirector.Construct(&computerDirector, (struct ComputerBuilder*)&lowCostComputerBuilder);
computer = lowCostComputerBuilder.computerBuilder.GetComputer((struct ComputerBuilder*)&lowCostComputerBuilder);
if (computer != NULL) {
computer->Show(computer);
}
_LowCostComputerBuilder(&lowCostComputerBuilder);
_ComputerDirector(&computerDirector);
}
客户端显示示例
-bash-4.2# ./computer
构建高性能电脑
开始构建电脑
第一步:创建主板
第二步:在主板上安装CPU
第三步:在主板上安装内存条
第四步:在主板上安装硬盘
输出电脑对象:
高端主板
i7八核八线程CPU
32G内存
2T大容量硬盘
构建低成本电脑
开始构建电脑
第一步:创建主板
第二步:在主板上安装CPU
第三步:在主板上安装内存条
第四步:在主板上安装硬盘
输出电脑对象:
普通主板
i3CPU
4G内存
256G硬盘