4. 建造者模式(Builder)

问题:对象有很多可选参数,构造函数参数列表越来越长。

核心:用链式调用一步步构建对象,最终 build() 出成品。

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type RequestBody = Record<string, unknown> | string | null;

class HttpRequest {
  method: HttpMethod;
  url: string;
  headers: Record<string, string>;
  body: RequestBody;

  constructor() {
    this.method = 'GET';
    this.url = '';
    this.headers = {};
    this.body = null;
  }
}

class HttpRequestBuilder {
  #req: HttpRequest = new HttpRequest();

  method(m: HttpMethod): this { this.#req.method = m; return this; }
  url(u: string): this        { this.#req.url = u;    return this; }
  header(k: string, v: string): this { this.#req.headers[k] = v; return this; }
  body(b: RequestBody): this  { this.#req.body = b;   return this; }

  build(): HttpRequest { return this.#req; }
}

const req = new HttpRequestBuilder()
  .method('POST')
  .url('/api/users')
  .header('Content-Type', 'application/json')
  .body({ name: 'Hok Keung' })
  .build();
package builder

type Request struct {
  Method  string
  URL     string
  Headers map[string]string
  Body    any
}

type RequestBuilder struct {
  req *Request
}

func NewRequestBuilder() *RequestBuilder {
  return &RequestBuilder{req: &Request{
    Method:  "GET",
    Headers: make(map[string]string),
  }}
}

func (b *RequestBuilder) Method(m string) *RequestBuilder {
  b.req.Method = m
  return b
}

func (b *RequestBuilder) URL(u string) *RequestBuilder {
  b.req.URL = u
  return b
}

func (b *RequestBuilder) Header(k, v string) *RequestBuilder {
  b.req.Headers[k] = v
  return b
}

func (b *RequestBuilder) Body(body any) *RequestBuilder {
  b.req.Body = body
  return b
}

func (b *RequestBuilder) Build() *Request {
  return b.req
}

实战场景

  • HTTP 请求构造:URL、method、headers、query、body、timeout、retry 都是可选参数,用 builder 可以让调用更清晰。
  • 数据库查询构造:复杂筛选、排序、分页、关联加载、聚合条件一步步追加,最后生成 SQL 或 ORM query。
  • 表单配置生成:低代码表单里,一个字段可能包含 label、校验规则、默认值、联动、权限和展示条件,适合链式构建。
  • 测试数据准备:单元测试经常需要构造“只改一两个字段”的用户、订单、权限对象,用 builder 比复制大对象更稳。
  • 邮件或消息模板:标题、收件人、抄送、附件、变量、优先级、发送时间等可选项很多,builder 能减少参数位置错误。
  • 图表配置:ECharts、Chart.js 这类图表配置层级深,builder 可以把常用场景包装成更可读的步骤。
  • CI/CD 流水线定义:构建、测试、缓存、部署、通知等步骤按需组合,最后生成 pipeline 配置。
  • 复杂领域对象:比如保险报价、旅行套餐、云服务器规格、套餐订阅,创建时字段多且有依赖关系,builder 可以集中校验。
  • AST 或表达式树:编译器、规则引擎、查询 DSL 里逐步拼装节点,最后得到一棵可执行或可序列化的树。
  • CLI 命令注册:命令名、描述、参数、选项、handler、子命令逐步声明,最后注册到命令行框架。