Builder パターン

複雑なオブジェクトの生成をメソッドチェーンで段階的に構築するデザインパターン

設計パターンビルド

Builder パターンとは

Builder パターンは、コンストラクタの引数が多いオブジェクトや、生成手順が複雑なオブジェクトを、メソッドチェーンで段階的に構築する GoF デザインパターンである。引数の順序を間違えるリスクを排除し、オプショナルなパラメータを柔軟に設定できる。

問題: 引数が多いコンストラクタ

// ❌ 引数が多い: どれが何か分からない、順序を間違えやすい
const config = new ServerConfig(3000, 'localhost', true, false, 30000, 100, '/api', true);

Builder で解決

class ServerConfig {
  readonly port: number;
  readonly host: string;
  readonly cors: boolean;
  readonly logging: boolean;
  readonly timeout: number;
  readonly maxConnections: number;

  private constructor(builder: ServerConfigBuilder) {
    this.port = builder.port;
    this.host = builder.host;
    this.cors = builder.cors;
    this.logging = builder.logging;
    this.timeout = builder.timeout;
    this.maxConnections = builder.maxConnections;
  }

  static builder() { return new ServerConfigBuilder(); }
}

class ServerConfigBuilder {
  port = 3000;
  host = 'localhost';
  cors = false;
  logging = true;
  timeout = 30000;
  maxConnections = 100;

  setPort(port: number) { this.port = port; return this; }
  setHost(host: string) { this.host = host; return this; }
  enableCors() { this.cors = true; return this; }
  disableLogging() { this.logging = false; return this; }
  setTimeout(ms: number) { this.timeout = ms; return this; }
  setMaxConnections(n: number) { this.maxConnections = n; return this; }

  build() { return new ServerConfig(this); }
}

// ✅ メソッドチェーン: 何を設定しているか明確
const config = ServerConfig.builder()
  .setPort(8080)
  .enableCors()
  .setTimeout(60000)
  .build();

TypeScript では Builder が不要なケースが多い

TypeScript ではオブジェクトリテラル + デフォルト値で Builder と同等のことが実現できる。

// TypeScript: オブジェクトリテラルで十分
interface ServerConfig {
  port?: number;
  host?: string;
  cors?: boolean;
  timeout?: number;
}

function createServer(config: ServerConfig = {}) {
  const { port = 3000, host = 'localhost', cors = false, timeout = 30000 } = config;
  // ...
}

createServer({ port: 8080, cors: true });

Java や C# では Builder パターンが頻繁に使われるが、TypeScript ではオブジェクトリテラルの方がシンプルだ。

Builder が有効なケース

  • 生成過程にバリデーションが必要 (build() 時に必須フィールドをチェック)
  • 不変オブジェクトを段階的に構築する
  • 流暢なインターフェース (Fluent Interface) を提供したい

AWS SDK の Builder パターン

AWS SDK v3 の Command オブジェクトは Builder 的なパターンを使っている。

const command = new PutCommand({
  TableName: 'Orders',
  Item: { orderId: '123', status: 'pending' },
  ConditionExpression: 'attribute_not_exists(orderId)',
});

ビルダー vs コンストラクタ

観点 コンストラクタ ビルダー
引数が少ない ✅ シンプル ❌ 過剰
引数が多い ❌ 読みにくい ✅ 読みやすい
オプション引数
バリデーション コンストラクタ内 build() 時

理論と実装の両面から学ぶなら関連書籍が参考になる。

関連用語