TypeScriptでデザインパターン[7.Builder]

# はじめに
Typescriptでデザインパターンをやっていくシリーズ（にする予定です）

結城 浩さんの「Java言語で学ぶデザインパターン入門」をTSに置き換えてTS力をあげていこうという趣旨です。

https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030

前回はこちら
- [TypeScriptでデザインパターン[1.Iterator]](https://qiita.com/zackey2/items/2fa106a8d68455b34c41)
- [TypeScriptでデザインパターン[2.Adapter]](https://qiita.com/zackey2/items/6c2292b88ff9f0cb2c91)
- [TypeScriptでデザインパターン[3.TemplateMethod]](https://qiita.com/zackey2/items/8c8cfdc1726f4b0c5c58)
- [TypeScriptでデザインパターン[4.FactoryMethod]](https://qiita.com/zackey2/items/eba421510cee6a7fbb60)
- [TypeScriptでデザインパターン[5.Singleton]](https://qiita.com/zackey2/items/54fb99d2f490fa29f9b0)
- [TypeScriptでデザインパターン[6.Prototype]](https://qiita.com/zackey2/items/ad82af1f6c45fd681c58)

# メモ
- `for ... in` は配列に使ってはいけない
    - 順序も保証されない
    - オブジェクトのキー値をループするためのもので、配列のキー以外も取れてしまうから
    - `forEach`を使う
    - `for ... of`を使う
- ファイル操作は`fs`
- JavaはStringBuilderを使ってたけど、JSは普通にstringの足し算できるけどどういう仕組みなんだろなとちょっと気になった
- 



# Code

```ts
const fs = require("fs");

namespace Builder {
  abstract class Builder {
    abstract makeTitle(title: string): void;
    abstract makeString(str: string): void;
    abstract makeItems(items: string[]): void;
    abstract close(): void;
  }

  class Director {
    private builder: Builder;

    constructor(builder: Builder) {
      this.builder = builder;
    }

    constract(): void {
      this.builder.makeTitle("タイトル");
      this.builder.makeString("これは本文");
      this.builder.makeItems(["りんご", "ごりら", "ラッパ"]);
      this.builder.makeString("これも本文");
      this.builder.makeItems(["プロテイン", "グルタミン", "ケトジェニック"]);
      this.builder.close();
    }
  }

  class TextBuilder extends Builder {
    private buffer: string = "";

    makeTitle(title: string): void {
      this.buffer += "===============================\n";
      this.buffer += `「${title}」\n\n`;
    }
    makeString(str: string): void {
      this.buffer += `□${str}\n\n`;
    }
    makeItems(items: string[]): void {
      items.forEach((item) => {
        this.buffer += `- ${item} \n`;
      });
      this.buffer += "\n";
    }

    close(): void {
      this.buffer += "===============================\n";
    }

    getResult(): string {
      return this.buffer;
    }
  }

  class MarkDownBuilder extends Builder {
    private buffer: string = "";

    makeTitle(title: string): void {
      this.buffer += `# ${title}\n\n`;
    }
    makeString(str: string): void {
      this.buffer += `${str}\n\n`;
    }
    makeItems(items: string[]): void {
      items.forEach((item) => {
        this.buffer += `- ${item} \n`;
      });

      this.buffer += "\n";
    }

    close(): void {
      this.buffer;
      fs.writeFileSync("output.txt", this.buffer);
    }

    getResult(): string {
      return "output.txt";
    }
  }

  class Main {
    main() {
      {
        const textBuilder = new TextBuilder();
        const director = new Director(textBuilder);
        director.constract();
        const result = textBuilder.getResult();
        console.log(result);
      }

      {
        const markDownBuilder = new MarkDownBuilder();
        const director = new Director(markDownBuilder);
        director.constract();
        const result = markDownBuilder.getResult();
        console.log(result);
        fs.readFile(result, "utf-8", (_err: any, data: any) => {
          console.log(data);
        });
      }
    }
  }
  new Main().main();
}


```