「増補改訂版Java言語で学ぶデザインパターン入門」の「Abstruct Factoryパターン」をC#で書いてみました。
GitHubにもコードを置いています。
参考
DesignPattern【Abstruct Factory】GitHub
コード
※ 一部のソースコードを表示上の理由で修正しています。正確なコードを参照したい場合、GitHubをご確認ください。
Factories
public abstract class Item
{
protected string caption;
public Item(string caption)
{
this.caption = caption;
}
public abstract string MakeHTML();
}
public abstract class Link : Item
{
protected string url;
public Link(string caption, string url) : base(caption)
{
this.url = url;
}
}
public abstract class Tray : Item
{
protected IList Item> tray = new List Item>();
public Tray(string caption) : base(caption)
{
}
public void Add(Item item)
{
tray.Add(item);
}
}
public abstract class Page
{
protected string title;
protected string author;
protected IList Item> content = new List Item>();
public Page(string title, string author)
{
this.title = title;
this.author = author;
}
public void Add(Item item)
{
content.Add(item);
}
public void Output()
{
try
{
string filename = $"{title}.html";
using var writer = File.CreateText(filename);
writer.Write(this.MakeHTML());
writer.Close();
Console.WriteLine($"{filename}を作成しました。");
}
catch (IOException ex)
{
Console.WriteLine(ex);
}
}
public abstract string MakeHTML();
}
public abstract class Factory
{
public static Factory GetFactory(string classname)
{
Factory factory = null;
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
factory = (Factory)assembly.CreateInstance(
classname,
false,
BindingFlags.CreateInstance,
null,
null,
null,
null
);
}
catch (TypeLoadException)
{
Console.Error.WriteLine($"クラス{classname}が見つかりません。");
}
catch (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);
}
ListFactories
public class ListFactory : Factory
{
public ListFactory()
{
}
public override Link CreateLink(string caption, string url)
{
return new ListLink(caption, url);
}
public override Page CreatePage(string title, string author)
{
return new ListPage(title, author);
}
public override Tray CreateTray(string caption)
{
return new ListTray(caption);
}
}
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>";
}
}
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");
var it = tray.GetEnumerator();
while (it.MoveNext())
{
buffer.Append(it.Current.MakeHTML());
}
buffer.Append(" /ul>\n");
buffer.Append(" /li>\n");
return buffer.ToString();
}
}
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");
var it = content.GetEnumerator();
while (it.MoveNext())
{
buffer.Append(it.Current.MakeHTML());
}
buffer.Append(" /ul>\n");
buffer.Append($" hr> address>{author} /address>\n");
buffer.Append($" /body> /html>\n");
return buffer.ToString();
}
}
TableFactories
public class TableFactory : Factory
{
public override Link CreateLink(string caption, string url)
{
return new TableLink(caption, url);
}
public override Page CreatePage(string title, string author)
{
return new TablePage(title, author);
}
public override Tray CreateTray(string caption)
{
return new TableTray(caption);
}
}
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";
}
}
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");
var it = tray.GetEnumerator();
while (it.MoveNext())
{
buffer.Append(it.Current.MakeHTML());
}
buffer.Append(" /tr> /table>");
buffer.Append(" /td>");
return buffer.ToString();
}
}
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");
var it = content.GetEnumerator();
while (it.MoveNext())
{
buffer.Append($" tr>{it.Current.MakeHTML()} /tr>");
}
buffer.Append(" /table>\n");
buffer.Append($" hr> address>{author} /address>\n");
buffer.Append($" /body> /html>\n");
return buffer.ToString();
}
}
Main
class Program
{
static void Main(string[] args)
{
if(args.Length != 1)
{
Console.WriteLine("Usage: dotnet AbstractFactory class.name.of.ConcreteFactory");
Console.WriteLine("Example 1: dotnet AbstractFactory listfactory.ListFactory");
Console.WriteLine("Example 2: dotnet AbstractFactory tablefactory.TableFactory");
Environment.Exit(0);
}
Factory factory = Factory.GetFactory(args[0]);
Link asahi = factory.CreateLink("朝日新聞", "https://www.asahi.com/");
Link yomiuri = factory.CreateLink("読売新聞", "https://www.yomiuri.co.jp/");
Link us_yahoo = factory.CreateLink("Yahoo!", "https://www.yahoo.com/");
Link jp_yahoo = factory.CreateLink("Yahoo!Japan", "https://www.yahoo.co.jp/");
Link excite = factory.CreateLink("Excite", "https://www.excite.co.jp/");
Link google = factory.CreateLink("Google", "https://www.google.co.jp/");
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(excite);
traysearch.Add(google);
Page page = factory.CreatePage("LinkPage", "結城 浩");
page.Add(traynews);
page.Add(trayyahoo);
page.Add(traysearch);
page.Output();
}
}
実行結果は以下のようになります。
$dotnet AbstractFactory.dll AbstractFactory.ListFactories.ListFactory
LinkPage.htmlを作成しました。
$dotnet AbstractFactory.dll AbstractFactory.TableFactories.TableFactory
LinkPage.htmlを作成しました。
その他のデザインパターンは以下の記事から確認してください。