「JAVA言語で学ぶデザインパターン入門」をC#で書いてみた【Abstruct Factoryパターン】

「増補改訂版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を作成しました。

その他のデザインパターンは以下の記事から確認してください。

「JAVA言語で学ぶデザインパターン入門」をC#で書いてみた【一覧】

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA