C#デザインパターン  - AbstractFactory

ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。
解説らしい解説は載せていませんので、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』も合わせてお読みください。

※当ソースは、Visual C# 2008 Express Editionで動作を確認しています。
  Visual Studio 2005をお使いの方は、ブログの記事を残しておきますので、そちらをご覧ください。



■Factory.cs
using System;

namespace Gushwell.DesignPatterns.BaseFactory {

public abstract class Factory {

public static Factory GetFactory(string classname) {
Factory factory = null;
try {
factory = (Factory)Activator.CreateInstance(Type.GetType(classname));
} catch (System.TypeLoadException) {
Console.Error.WriteLine("クラス " + classname + " が見つかりません。");
} catch (System.Exception e) {
Console.Error.WriteLine(e.StackTrace);
}
return factory;
}

public abstract Link CreateLink(string caption, string url);
public abstract Tray CreateTray(string caption);
public abstract Page CreatePage(string title, string author);
}
}

■Item.cs
using System;

namespace Gushwell.DesignPatterns.BaseFactory {

public abstract class Item {
protected string caption;

public Item(string caption) {
this.caption = caption;
}

public abstract string MakeHTML();
}
}

■Link.cs
using System;

namespace Gushwell.DesignPatterns.BaseFactory {

public abstract class Link : Item {
protected string url;

public Link(string caption, string url)
: base(caption) {
this.url = url;
}
}
}

■Page.cs
using System;
using System.Text;
using System.Collections.Generic;
using System.IO;

namespace Gushwell.DesignPatterns.BaseFactory {

public abstract class Page {
protected string title;
protected string author;
protected List<Item> content = new List<Item>();

public Page(string title, string author) {
this.title = title;
this.author = author;
}

public void Add(Item item) {
this.content.Add(item);
}

public void Output() {
try {
string filename = this.title + ".html";
StreamWriter writer = new StreamWriter(filename, false, Encoding.Default);
writer.Write(this.MakeHTML());
writer.Close();
Console.WriteLine(filename + " を作成しました。");
} catch (System.IO.IOException e) {
Console.Error.WriteLine(e.StackTrace);
}
}

public abstract string MakeHTML();
}
}

■Tray.cs
using System;
using System.Collections.Generic;

namespace Gushwell.DesignPatterns.BaseFactory {

public abstract class Tray : Item {
protected List<Item> tray = new List<Item>();

public Tray(string caption)
: base(caption) {
}

public void Add(Item item) {
tray.Add(item);
}
}
}


■ListFactory.cs
using System;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.List {

public class ListFactory : Factory {
public override Link CreateLink(string caption, string url) {
return new ListLink(caption, url);
}

public override Tray CreateTray(string caption) {
return new ListTray(caption);
}

public override Page CreatePage(string title, string author) {
return new ListPage(title, author);
}
}
}

■ListLink.cs
using System;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.List {

public class ListLink : Link {
public ListLink(string caption, string url)
: base(caption, url) {
}

public override string MakeHTML() {
return " <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
}
}
}

■ListPage.cs
using System;
using System.Text;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.List {

public class ListPage : Page {
public ListPage(string title, string author)
: base(title, author) {
}

public override string MakeHTML() {
StringBuilder buffer = new StringBuilder();
buffer.Append("<html><head><title>" + title + "</title></head>\n");
buffer.Append("<body>\n");
buffer.Append("<h1>" + title + "</h1>\n");
buffer.Append("<ul>\n");
content.ForEach(item =>
buffer.Append(item.MakeHTML()));
buffer.Append("</ul>\n");
buffer.Append("<hr><address>" + author + "</address>");
buffer.Append("</body></html>\n");
return buffer.ToString();
}
}
}

■ListTray.cs
using System;
using System.Text;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.List {

public class ListTray : Tray {
public ListTray(string caption)
: base(caption) {
}

public override string MakeHTML() {
StringBuilder buffer = new StringBuilder();
buffer.Append("<li>\n");
buffer.Append(caption + "\n");
buffer.Append("<ul>\n");
tray.ForEach(item =>
buffer.Append(item.MakeHTML()));
buffer.Append("</ul>\n");
buffer.Append("</li>\n");
return buffer.ToString();
}
}
}


■TableFactory.cs
using System;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.Table {

public class TableFactory : Factory {
public override Link CreateLink(string caption, string url) {
return new TableLink(caption, url);
}

public override Tray CreateTray(string caption) {
return new TableTray(caption);
}

public override Page CreatePage(string title, string author) {
return new TablePage(title, author);
}
}
}

■TableLink.cs
using System;
using Gushwell.DesignPatterns.BaseFactory;


namespace Gushwell.DesignPatterns.Table {

public class TableLink : Link {
public TableLink(string caption, string url)
: base(caption, url) {
}

public override string MakeHTML() {
return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
}
}
}

■TablePage.cs
using System;
using System.Text;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.Table {

public class TablePage : Page {
public TablePage(string title, string author)
: base(title, author) {
}

public override string MakeHTML() {
StringBuilder buffer = new StringBuilder();
buffer.Append("<html><head><title>" + title + "</title></head>\n");
buffer.Append("<body>\n");
buffer.Append("<h1>" + title + "</h1>\n");
buffer.Append("<table width=\"80%\" border=\"3\">\n");

content.ForEach(item =>
buffer.Append("<tr>" + item.MakeHTML() + "</tr>"));

buffer.Append("</table>\n");
buffer.Append("<hr><address>" + author + "</address>");
buffer.Append("</body></html>\n");
return buffer.ToString();
}
}
}

■TableTray.cs
using System;
using System.Text;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns.Table {

public class TableTray : Tray {
public TableTray(string caption)
: base(caption) {
}

public override string MakeHTML() {
StringBuilder buffer = new StringBuilder();
buffer.Append("<td>");
buffer.Append("<table width=\"100%\" border=\"1\"><tr>");
buffer.Append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" +
tray.Count + "\"><b>" + caption + "</b></td>");
buffer.Append("</tr>\n");
buffer.Append("<tr>\n");

tray.ForEach(item =>
buffer.Append(item.MakeHTML()));

buffer.Append("</tr></table>");
buffer.Append("</td>");
return buffer.ToString();
}
}
}


■Program.cs
using System;
using Gushwell.DesignPatterns.BaseFactory;

namespace Gushwell.DesignPatterns {
public class Program {
public static void Main(string[] args) {
if (args.Length != 1) {
const string ListFactoryClass =
"Gushwell.DesignPatterns.List.ListFactory";
const string TableFactoryClass =
"Gushwell.DesignPatterns.Table.TableFactory";
Console.WriteLine("Usage: AbstractFactory TypeName");
Console.WriteLine("Example 1: AbstractFactory " + ListFactoryClass);
Console.WriteLine("Example 2: AbstractFactory " + TableFactoryClass);
return;
}
Factory factory = Factory.GetFactory(args[0]);

Link asahi = factory.CreateLink("朝日新聞", "http://www.asahi.com/");
Link yomiuri = factory.CreateLink("読売新聞", "http://www.yomiuri.co.jp/");

Link us_yahoo = factory.CreateLink("Yahoo!", "http://www.yahoo.com/");
Link jp_yahoo = factory.CreateLink("Yahoo!Japan", "http://www.yahoo.co.jp/");
Link excite = factory.CreateLink("Excite", "http://www.excite.com/");
Link google = factory.CreateLink("Google", "http://www.google.com/");

Tray traynews = factory.CreateTray("新聞");
traynews.Add(asahi);
traynews.Add(yomiuri);

Tray trayyahoo = factory.CreateTray("Yahoo!");
trayyahoo.Add(us_yahoo);
trayyahoo.Add(jp_yahoo);

Tray traysearch = factory.CreateTray("サーチエンジン");
traysearch.Add(trayyahoo);
traysearch.Add(excite);
traysearch.Add(google);

Page page = factory.CreatePage("LinkPage", "結城 浩");
page.Add(traynews);
page.Add(traysearch);
page.Output();
}
}
}