C#入門(第17回)

前回振り返り

Factory Method パターン

Factory Methodパターンとは、インスタンスの作り方をスーパークラスで定め、具体的な処理をサブクラスで行うパターンです。オブジェクトの生成と具体的な処理を分離することで、より柔軟にオブジェクトを利用することができます。

Factory Method パターンのクラス図は、CreatorとProductの2つの抽象クラスを持ちます。Creatorは、Productを生成するためのファクトリメソッドを持ちます。そして、ConcreteCreatorは、具体的なProductを生成するために、Creatorを継承してファクトリメソッドを実装します。ConcreteProductは、Productの具体的な実装を提供します。

Factory Method パターンのクラス図

前回演習問題の解答 例

問題1

問題文

Factory Method パターン を作成してみましょう。

wikipedia のJava実装例をC#で記述してみましょう。


解答例

// Creatorに相当する
using System;
using System.Collections;

abstract class ListPrinter
{
    // anOperationに相当する
    public void printList(List<String> list)
    {
        Comparer<String> comparator = createComparator();
        list = new List<String>(list);

        list.Sort(comparator);

        foreach (String item in list)
        {
            Console.WriteLine(item);
        }
    }

    // factoryMethodに相当する
    protected abstract Comparer<String> createComparator();
}

// ConcreteCreatorに相当する
class DictionaryOrderListPrinter : ListPrinter
{
    protected override Comparer<String> createComparator()
    {
        return new DictionaryOrderComparator();
    }
}

class StateB : State
{

    private int count = 0;
    public void writeName(StateContext stateContext, String name)
    {
        Console.WriteLine(name.ToUpper());
        // StateBのwriteName()が2度呼び出された後にコンテキストをStateAに遷移する
        if (++count > 1)
        {
            stateContext.setState(new StateA());
        }
    }
}
public class StateContext
{
    private State myState;
    public StateContext()
    {
        setState(new StateA());
    }

    // 通常は、Stateインタフェースを実装しているクラスによってのみ呼び出される
    public void setState(State newState)
    {
        this.myState = newState;
    }

    public void writeName(String name)
    {
        this.myState.writeName(this, name);
    }
}
// ComparerがProductに相当する

// ConcreteProductに相当する
class DictionaryOrderComparator : Comparer<String>
{
    public override int Compare(string? str1, string? str2)
    {
        return str1.CompareTo(str2);
    }
}

// ConcreteCreatorに相当する
class LengthOrderListPrinter : ListPrinter
{
    protected override Comparer<String> createComparator()
    {
        return new LengthOrderComparator();
    }
}

// ConcreteProductに相当する
class LengthOrderComparator : Comparer<String>
{
    public override int Compare(string? str1, string? str2)
    {
        return str1.Length - str2.Length;
    }
}

// メインクラス
public class FactoryMethodSample
{
    public static void Main(string[] args)
    {
        List<string> list = new List<string>(new[] { "いちご", "もも", "いちじく" });

        Console.WriteLine("五十音順で表示:");
        new DictionaryOrderListPrinter().printList(list);

        Console.WriteLine();

        Console.WriteLine("長さ順で表示:");
        new LengthOrderListPrinter().printList(list);
    }
}

問題2

問題文

問1のクラスを身近なものにアレンジしてみましょう。


解答例

    abstract class Creator
    {
        public abstract Product FactoryMethod();
    }
    class ConcreteCreator : Creator
    {
        public override Product FactoryMethod()
        {
            return new ConcreteProduct();
        }
    }
    abstract class Product
    {
        public abstract void Use();
    }
    class ConcreteProduct : Product
    {
        public override void Use()
        {
            Console.WriteLine("ConcreteProductを使います。");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Creator creator = new ConcreteCreator();
            Product product = creator.FactoryMethod();
            product.Use();
        }
    }

今回の演習問題

問題1

問題文

Template Method パターン を作成してみましょう。

wikipedia のJava実装例をC#で記述してみましょう。

問題2

問題文

問1のクラスを身近なものにアレンジしてみましょう。

コメント