LoginSignup
10
10

More than 5 years have passed since last update.

Builderパターン

Last updated at Posted at 2015-03-18

Builderパターン(インスタンスを作る)

複雑なインスタンスを組み立てる

---目的---

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

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

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


---実施---

  1. Builder = 文章を構成するためのメソッドを定めた抽象クラス
  2. Director = 1つの文章を作るクラス
  3. TextBuilder = プレーンテキスト(普通の文字列)を使って文章を作るクラス
  4. HTMLBuilderHTML = ファイルを使って文章を作るクラスMain動作テスト用のクラス
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()
文章を完成させるメソッド


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()
文書を作るメソッド。このメソッドを呼ぶと、文書が構築されます。


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クラスの抽象メソッドを実装している


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クラスの抽象メソッドを実装している


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インスタンス作成

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10