SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンの使い方

デザインパターンの使い方: Builder

インターフェイスと実装の分離を実現するBuilderパターン

 ビルダーオブジェクトの作成とディレクターへの引き渡しをクライアントが担当しなければならないという点が、Builderパターンのもう1つの特徴です。

 では、ビルダーはどのような実装になるのでしょうか? リスト4に、抽象クラスとして作成されたビルダーの構造の一例を示します。リスト5は、HTMLビルダーの実装です。

リスト4 ビルダーの例
public abstract class CatalogReportBuilder {
   static final String EOL = System.getProperty("line.separator");
   private StringBuilder report = new StringBuilder();

   public String getReport() {
      return report.toString();
   }

   abstract public void generateHeader();
   abstract public void generateDetail(Material material);
   abstract public void generateSummary();

   protected void appendLine(String text) {
      report.append(text);
      report.append(EOL);
   }
}

 このビルダークラスはreportへの参照を保持しています。生成アルゴリズムの部分を実行する際に、このreportに内容が書き込まれます。リスト6に、また別のビルダーの例を示します。

リスト5 HTMLビルダーの例
public class HtmlCatalogBuilder extends CatalogReportBuilder {
   @Override
   public void generateDetail(Material material) {
      appendLine(String.format("<tr>%s%s%s%s</tr>",
            td(material.getTitle()),
            td(material.getAuthor()),
            td(material.getClassification()),
            td(material.getYear())));
   }

   @Override
   public void generateHeader() {
      appendLine("<body>");
      appendLine("<table>");
      appendLine(String.format("<tr>%s%s%s%s</tr>",
            th("Title"),
            th("Auth/Dir"),
            th("Classification"),
            th("Year")));
   }

   @Override
   public void generateSummary() {
      appendLine("</table>");
      appendLine("</body>");
   }

   private String td(String element) {
      return tag(element, "td");
   }

   private String th(String element) {
      return tag(element, "th");
   }

   private String tag(String element, String tag) {
      return String.format("<%s>%s</%s>", tag, element, tag);
   }
}
リスト6 印刷用ビルダーの例
public class PrintCatalogBuilder extends CatalogReportBuilder {
   private static final String ROW_LAYOUT = "%s %s %s %s";
   private static final int YEAR_WIDTH = 4;
   private static final int CLASSIFICATION_WIDTH = 14;
   private static final int AUTHOR_WIDTH = 20;
   private static final int TITLE_WIDTH = 24;

   @Override
   public void generateDetail(Material material) {
      appendLine(format(
            material.getTitle(),
            material.getAuthor(),
            material.getClassification(),
            material.getYear()));
   }

   @Override
   public void generateHeader() {
      String header = format("Title", "Auth/Dir",
                             "Classification", "Year");
      appendLine(header);
      appendLine(replaceWithDashes(header));
   }

   private String replaceWithDashes(String header) {
      return header.replaceAll("\\S", "-");
   }

   @Override
   public void generateSummary() {
      appendLine("");
   }

   private String format(
         String title, String author, String classification,
         String year) {
      return String.format(ROW_LAYOUT,
            pad(title, TITLE_WIDTH),
            pad(author, AUTHOR_WIDTH),
            pad(classification, CLASSIFICATION_WIDTH),
            pad(year, YEAR_WIDTH));
   }

   private String pad(String text, int width) {
      if (text.length() >= width)
         return text.substring(0, width);

      StringBuilder spaces = new StringBuilder(text);
      for (int i = 0; i < width - text.length(); i++)
         spaces.append(' ');
      return spaces.toString();
   }
}

 Builderパターンは、Template Methodパターンによく似ています。Template Methodパターンを使用する場合は、アルゴリズムの構造と、そのアルゴリズムの実装に必要な細かい共通事項をベースクラスで定義します。それを拡張クラスで「穴埋め」することによって、アルゴリズムを完成させます。BuilderパターンがTemplate Methodパターンと大きく異なるのは、その目的がオブジェクトを生成することであり、アルゴリズムを実行することではないという点です。Builderパターンは「分離型」のTemplate Methodパターンとも考えられます。アルゴリズムの定義は1つのクラス(ディレクター)で行われますが、実装は別のビルダー階層にて行われます。

 Builderパターンは、役割分担を明確にするだけでなく、インターフェイスと実装の分離を実現する代表的な事例です。また、パターンを利用することで、パターンを使用しない場合に起こりうる重複をかなりの程度防ぐことができます。

図1 Builderパターン
図1 Builderパターン

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Jeff Langr(Jeff Langr)

本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3012 2008/09/30 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー