2006年01月24日

Builderパターン -複雑なインスタンスを組み立てる

  
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。なお、移植後のコードの公開に関しては、結城氏の了解を得ています。
なお、当ソースは、Visual C# 2005 Express Editionで動作を確認しています。



Builder
using System;

namespace Gushwell.DesignPatterns {
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();
}
}



TextBuilder
using System;
using System.Text;

namespace Gushwell.DesignPatterns {
public class TextBuilder : Builder {
// このフィールドに文書を構築していく
private StringBuilder buffer = new StringBuilder();

// 完成した文書
virtual public string Result {
get { return buffer.ToString(); }
}

// プレーンテキストでのタイトル
public override void MakeTitle(string title) {
buffer.Append("==============================\n"); // 飾り線
buffer.Append("『" + title + "』\n"); // 『』つきのタイトル
buffer.Append("\n"); // 空行
}

// プレーンテキストでの文字列
public override void MakeString(string str) {
buffer.Append('■' + str + "\n"); // ■つきの文字列
buffer.Append("\n"); // 空行
}

// プレーンテキストでの箇条書き
public override void MakeItems(string[] items) {
for (int i = 0; i < items.Length; i++) {
buffer.Append(" ・" + items[i] + "\n"); // ・つきの項目
}
buffer.Append("\n"); // 空行
}

// 文書の完成
public override void Close() {
buffer.Append("==============================\n"); // 飾り線
}
}
}



HTMLBuilder
using System;
using System.IO;

namespace Gushwell.DesignPatterns {
public class HTMLBuilder : Builder {
private string filename; // 作成するファイル名
private StreamWriter writer; // ファイルに書き込む

// 完成した文書
public virtual string Result {
get { return filename; } // ファイル名を返す
}

// HTMLファイルでのタイトル
public override void MakeTitle(string title) {
filename = title + ".html"; // タイトルを元にファイル名決定
try {
writer = new StreamWriter(filename, false);
} catch (System.IO.IOException e) {
Console.WriteLine(e.StackTrace);
}
// タイトルを出力
writer.WriteLine("<html><head><title>" + title + "</title></head><body>");
writer.WriteLine("<meta http-equiv=\"Content-Type\" " +
"content=\"text/html; charset=UTF-8\" />");
writer.WriteLine("<h1>" + title + "</h1>");
}

// HTMLファイルでの文字列
public override void MakeString(string str) {
writer.WriteLine("<p>" + str + "</p>"); // <p>タグで出力
}

// HTMLファイルでの箇条書き
public override void MakeItems(string[] items) {
writer.WriteLine("<ul>"); // <ul>と<li>で出力
for (int i = 0; i < items.Length; i++) {
writer.WriteLine("<li>" + items[i] + "</li>");
}
writer.WriteLine("</ul>");
}

// 文書の完成
public override void Close() {
writer.WriteLine("</body></html>"); // タグを閉じる
writer.Close(); // ファイルをクローズ
}
}
}



Director
using System;

namespace Gushwell.DesignPatterns {
public class Director {
private Builder builder;

public Director(Builder builder) {
// Builderのサブクラスのインスタンスが与えられるので、
// builderフィールドに保持しておく。
this.builder = builder;
}

public virtual void Construct() {
// 文書構築
builder.MakeTitle("Greeting"); // タイトル
builder.MakeString("朝から昼にかけて"); // 文字列
builder.MakeItems(new string[]
{ "おはようございます。", "こんにちは。" });
builder.MakeString("夜に"); // 別の文字列
builder.MakeItems(new string[]
{ "こんばんは。", "おやすみなさい。", "さようなら。" });
builder.Close(); // 文書を完成させる
}
}
}



Program
using System;

namespace Gushwell.DesignPatterns {
public class Program {
public static void Main(string[] args) {
if (args.Length != 1) {
Usage();
return;
}
if (args[0].Equals("plain")) {
TextBuilder textbuilder = new TextBuilder();
Director director = new Director(textbuilder);
director.Construct();
string result = textbuilder.Result;
Console.WriteLine(result);
} else if (args[0].Equals("html")) {
HTMLBuilder htmlbuilder = new HTMLBuilder();
Director director = new Director(htmlbuilder);
director.Construct();
string filename = htmlbuilder.Result;
Console.WriteLine(filename + "が作成されました。");
} else {
Usage();
return;
}
}

public static void Usage() {
Console.WriteLine("Usage: BuilderSample plain プレーンテキストで文書作成");
Console.WriteLine("Usage: BuilderSample html HTMLファイルで文書作成");
}
}
}


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/50312030