Builderパターン

Builderパターン(インスタンスを作る)
=
##複雑なインスタンスを組み立てる##


###---目的---###
作成するプログラムがとても大きくて複雑なものを作る時に
まずシンプルな全体像を作成して、そこから細かい所を作っていきたい。
**(具体例)**
動物園を例にしてみます。

登場するキャラクター
①動物園作りの仕事をしている私、②キリン、③ゾウ、④ライオン

(1)新しく動物園を作る事になった
(2)どんな動物が入るかわからないけど3種類の動物を想定して
　動物が入るゲージを作る、入場ゲートを作る、入場料を決める①
⇒大雑把に入る動物は決まってないけれど動物園が完成
(3)動物園にやってくる動物が決まる(キリン、ゾウ、ライオン)
　それぞれの動物によって必要なエサ、ゲージの形状が決まる
(4)入る動物が決まり、ゲージの形状など具体的に細かい所まで作り込んだ
　動物園が完成する
と言うイメージでいます。


---
###---実施---###
1. **Builder** = 文章を構成するためのメソッドを定めた抽象クラス
1. **Director** = 1つの文章を作るクラス
1. **TextBuilder** = プレーンテキスト(普通の文字列)を使って文章を作るクラス
2. **HTMLBuilderHTML** = ファイルを使って文章を作るクラスMain動作テスト用のクラス


```java:Builder.java
public abstract class Builder {
     public abstract void makeTitle(String title);
     public abstract void makeString(String str);
     public abstract void makeItems(String[] items);
     public abstract void close();
}
```
**makeTitle(String title)**
タイトル構築メソッド
**makeString(String str)**
文字列構築メソッド
**makeItems(String[] items)**
箇条書き構築メソッド
**close()**
文章を完成させるメソッド

---

```java:Director.java
public class Director {
     private Builder builder;
     public Director(Builder buider){
          this.builder = buider;
     }
     public void constract(){
          builder.makeTitle("Greeting");
          builder.makeString("朝から昼にかけて");
          builder.makeItems(new String[] {
                    "おはようございます",
                    "こんにちは"
          });
          builder.makeString("夜に");
          builder.makeItems(new String[] {
                    "こんばんは",
                    "おやすみなさい",
                    "さようなら"
          });
          builder.close();
     }
}
```
**constract()**
文書を作るメソッド。このメソッドを呼ぶと、文書が構築されます。


---
```java:TextBuilder.java
public class TextBuilder extends Builder{
     private StringBuffer buffer = new StringBuffer();
     public void makeTitle(String title){
          buffer.append("====================\n");
          buffer.append("『"+title+"』");
          buffer.append("\n");
     }
     public void makeString(String str){
          buffer.append("■"+str+"\n");
          buffer.append("\n");
     }
     public void makeItems(String[] items){
          for(int i = 0; i <items.length; i++){
               buffer.append("   *" + items[i] + "\n");
          }
          buffer.append("\n");
     }
     public void close(){
          buffer.append("====================\n");
     }
     public String getResult(){
          return buffer.toString();
     }
}
```
Builderクラスの抽象メソッドを実装している


---
```java:HTMLBuilder.java
public class HTMLBuilder extends Builder {
     private String filename;
     private PrintWriter writer;
     public void makeTitle(String title) {
          filename = title + ".html";
          try{
               writer = new PrintWriter(new FileWriter(filename));
          }catch(IOException e){
               e.printStackTrace();
          }
          writer.println("<html><head><title>" + title +"</title></head><body>");
          //タイトルを出力
          writer.println("<h1>" + title + "</h1>");
     }
     public void makeString(String str) {
          writer.println("<p>" + str +"</p>");
     }
     public void makeItems(String[] items) {
          writer.println("<ul>");
          for(int i = 0; i < items.length; i++){
               writer.println("<li>" + items[i] + "</li>");
          }
          writer.println("</ul>");
     }
     public void close() {
          writer.println("</body></html>");
          writer.close();
     }
     public String getResult(){
          return filename;
     }
}
```
Builderクラスの抽象メソッドを実装している

---
```java:Main.java
public class Main {
     public static void main(String[] args){
          if(args.length !=1){
               usage();
               System.exit(0);
          }
          if(args[0].equals("plain")){
               TextBuilder textbuilder = new TextBuilder();
               Director director = new Director(textbuilder);
               director.constract();
               String result = textbuilder.getResult();
               System.out.println(result);
          }else if(args[0].equals("html")){
               HTMLBuilder htmlbuilder = new HTMLBuilder();
               Director director = new Director(htmlbuilder);
               director.constract();
               String filename = htmlbuilder.getResult();
               System.out.println(filename + "が作成されまし。");
          }else{
               usage();
          }System.exit(0);
     }
     public static void usage(){
          System.out.println("Usage: java Main plain     プレーンテキストで文書作成");
          System.out.println("Usage: java Main html     htmlで文書作成");
     }
}
```

---
###---結果---###
mainメソッドを実行する際に引数の値が、
**plain**の場合はテキストで出力される。
**html**の場合はHTML形式で出力される。

---
###---まとめ---###
- 誰が何を知っているか
- どのクラスがどのメソッドを使えるか(使ってよいか)に注意してプログラミングをする必要がある
- 例ではMainクラスはBuilderクラスのメソッドを知らない
- MainクラスはDirectorクラスのconstractメソッドだけを呼び出す。
- DirectorクラスはBuilderクラスのメソッドを利用してロジックを作成しているが、
実際に利用しているクラスが何なのかは知らない。
- Directorクラスが自分の利用しているBuilderクラスのサブクラスを知らないのは良い。
=「知らないからこそ入れ替えができる」

###「**交換可能性**」について常に意識する###

～上記例での流れ～
(1)Builder(抽象クラス)に抽象メソッドを作成
(2)Directorのコンストラクタの引数にBuilder(実装クラス)を入れてインスタンス生成
(3)Builder(抽象クラス)を実装したクラスを作成
(4)Directorクラスのメソッド内でBuilder(実装クラス)のインスタンスのメソッドを使用
(5)mainメソッド内でBuilder(実装クラス)のインスタンスを作成し、Directorのコンストラクタの引数に入れてDirectorインスタンス作成