定义
建造者模式的目标是分离对象的创建过程和对象的表示。对象的表示即是对象描述,也就是通俗意义上对象的属性和行为。其核心思想是将一个复杂对象的构建算法与它的部件及组装分离,使得构建算法和部件及组装可独立变化。
对象的构建算法和部件及组装可独立变化,这是创建者模式给我们带来的最大优势。由于对象的构建过程和部件及组装处于分离状态,因此彼此可以独自变化;所以相同的构建算法可以根据不同的部件及组装创建出不同的产品,不同的创建算法亦可以复用相同的组件及组装从而创建不同的产品。
在创建复杂对象时,创建者模式是较好的选择。一般情况下,创建者模式主要适用于以下应用场景。
- 相同的方法,不同的执行顺序,生产不同的对象。
- 一个复杂对象由多个部件或零件,可以通过不同的装配流程,产生不同的结果。
- 初始化一个复杂的对象,参数特别多而且很多参数有默认值。
构建者模式也是分而治之理念的一种应用,设计者可根据实际场景将复杂的对象拆分成多个部件及组装。在实际构建构建过程中,这些部件及组装按照组装算生产需要的产品。基于这些部件和组装,不同的组装算法会组装出不同的产品。而这种组装模式允许组装算法和部件及组装分别变化。
模式角色
建造者模式一般包括这么几个角色:
- Product:建造者需要创建的产品对象
- Builder:建造者抽象类,规范产品对象的各个组件及组装,一般由子类实现具体的组件及组装过程。
- ConcreteBuilder:具体的Builder类,根据不同的业务逻辑,具体化对象的各个组件及组装过程实现。
- Director:建造者指挥导向器,导向器负责配置Builder,按照客户规定的算法指挥Builder生产Product产品。
实现
构建者模式按照实现方式,一般有如下两种实现方式。第一种是链式实现,第二种是内部静态构建实现。由于C语言语法不支持内部静态类,所以这里只介绍C语言的建造者模式链式实现。
链式实现是建造者模式的一种较常见的实现方式,例如JDK中的StringBuilder就采用这种链式实现。链式调用直接使用Builder对象进行组装,具体使用时每个组件的装配过程都返回自身,从而实现链式调用。此实现省略了Director指挥器,将Director指挥器和客户端直接融合。
基于C语言语法实现的链式调用StringBulder,具体代码实现如下:
StringBuilder声明文件 string_builder.h
#pragma once
typedef struct StringBuilder* StringBuilder;
typedef struct StringBuilderAttr* StringBuilderAttr;
struct StringBuilder
{
// 成员属性
StringBuilderAttr attr;
// 成员函数
StringBuilder (*append)(StringBuilder self, const char* sz);
StringBuilder (*appendAt)(StringBuilder self, const char* sz, const int offset);
char* (*toString)();
};
StringBuilder createStringBuilder(int capacity);
void detroyStringBuilder(StringBuilder const self);
StringBuilder定义实现文件string_builder.c
#include "string_builder.h"
#include <stdlib.h>
#include <string.h>
struct StringBuilderAttr
{
// 字符串存储器
char* value;
// 字符串长度
size_t count;
// 字符串容量
size_t capacity;
};
static StringBuilder append(StringBuilder self, const char* sz)
{
StringBuilderAttr attr = self->attr;
size_t length = strlen(sz);
if (length > attr->capacity - attr->count)
{
char* p = realloc(attr->value, attr->capacity * 2);
attr->value = p;
attr->capacity = attr->capacity * 2;
}
if (length < attr->capacity - attr->count)
{
memcpy(attr->value + attr->count, sz, length + 1);
attr->count += length;
}
return self;
}
static StringBuilder appendAt(StringBuilder self, const char* sz, const int offset)
{
return self;
}
static char* toString(StringBuilder self)
{
if (NULL != self->attr)
{
return self->attr->value;
}
return NULL;
}
static const int DEFAULT_CAPACITY = 16;
static void detroyStringBuilderAttr(StringBuilderAttr const attr)
{
if (NULL != attr)
{
if (NULL != attr->value)
{
free(attr->value);
}
free(attr);
}
}
static StringBuilderAttr createStringBuilderAttr(int capacity)
{
StringBuilderAttr attr = (StringBuilderAttr)malloc(sizeof(struct StringBuilderAttr));
if (NULL != attr)
{
int length = (capacity > DEFAULT_CAPACITY) ? capacity : DEFAULT_CAPACITY;
attr->value = (char*)malloc(length + 1);
memset(attr->value, 0, length + 1);
attr->capacity = length;
attr->count = 0;
return attr;
}
detroyStringBuilderAttr(attr);
return NULL;
}
StringBuilder createStringBuilder(int capacity)
{
StringBuilder self = (StringBuilder)malloc(sizeof(struct StringBuilder));
if (NULL != self)
{
self->attr = createStringBuilderAttr(capacity);
self->append = append;
self->appendAt = appendAt;
self->toString = toString;
return self;
}
detroyStringBuilder(self);
return NULL;
}
void detroyStringBuilder(StringBuilder const self)
{
if (NULL != self)
{
if (NULL != self->attr)
{
detroyStringBuilderAttr(self->attr);
}
free(self);
}
}
链式调用应用举例main.c
int main()
{
struct StringBuilder * builder = createStringBuilder(128);
builder->append(builder, "123")
->append(builder, "321")
->append(builder, "562");
char* str = builder->toString(builder);
fprintf(stdout, "builder string is %s", str);
return 0;
}
编译运行,命令行输出
builder string is 123321562
总结
构建者模式是一种常见的创建型设计模式,此模式基于分而治之的理念将产品的构建算法和产品的组件和组装分离,从而实质彼此的独立变化。所以相同的构建算法可以根据不同的部件及组装创建出不同的产品,不同的创建算法亦可以复用相同的组件及组装从而创建不同的产品。