nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

Simple Factory (C#)

Simple Factoryパターンについて

実際にはデザインパターンではありません。プログラミングのイディオムとなります。

クラス図

f:id:nprogram:20181116062243p:plain

実行イメージ

Cheeseピザの材料を準備します。
Cheeseピザを焼きます。
Cheeseピザをカットします。
Cheeseピザを箱に収納します。
[Check Pizza Name] Name : Cheese
[Check Pizza Box]
Cheeseピザを箱に収納します。


Tomatoピザの材料を準備します。
Tomatoピザを焼きます。
Tomatoピザをカットします。
Tomatoピザを箱に収納します。
[Check Pizza Name] Name : Tomato
[Check Pizza Box]
Tomatoピザを箱に収納します。

コードの説明

ピザストアを例に説明します。

ピザを作る(Pizzaクラスのインスタンスの生成)は、Factoryクラス(コード例ではSimplePizzaFactoryクラス)が担当します。

Pizzaクラスは実体がないインタフェースクラスです。

クライアントクラスである(PizzaStores )は、実体(具象Pizzaクラス:CheesePizzaクラス)を参照しません。

ファクトリークラスのみが、具象Pizzaクラスを扱うだた1つのクラスであるべきです。

具象Pizzaクラスのインスタンスの生成もファクトリークラスのみで行うようにすることで、コードのあちこちで具象Pizzaクラスのインスタンスが生成されることを防ぎます。

コード

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            PizzaStores pizzaStores = new PizzaStores();

            IPizza cheesePizza;

            cheesePizza = pizzaStores.orderPizza("Cheese");

            Console.WriteLine("[Check Pizza Name] Name : {0}", cheesePizza.GetPizzaName());
            Console.WriteLine("[Check Pizza Box] ");
            cheesePizza.Box();

            Console.WriteLine();
            Console.WriteLine();

            IPizza tomatoPizza;

            tomatoPizza = pizzaStores.orderPizza("Tomato");

            Console.WriteLine("[Check Pizza Name] Name : {0}", tomatoPizza.GetPizzaName());
            Console.WriteLine("[Check Pizza Box] ");
            tomatoPizza.Box();

            Console.ReadLine();
        }
    }

    /// <summary>
    /// ファクトリーのクライアントクラス
    /// </summary>
    public class PizzaStores
    {
        SimplePizzaFactory factory = new SimplePizzaFactory();

        public IPizza orderPizza(string type)
        {

            IPizza pizza = factory.createPizza(type);

            if (pizza == null) return null;

            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();

            return pizza;
        }
    }

    /// <summary>
    /// ピザを作成するファクトリークラス
    /// </summary>
    /// <remarks>
    /// このクラスは、具象Pizzaクラス(CheesePizaクラスとか、TomatoPizzaクラス)を参照するアプリケーションで唯一のクラスであるべき
    /// </remarks>
    public class SimplePizzaFactory
    {
        public IPizza createPizza(string type)
        {
            IPizza pizza = null;

            if (type == "Cheese")
            {
                pizza = new CheesePizza(type);

            }
            else if (type == "Tomato")
            {
                pizza = new CheesePizza(type);
            }

            return pizza;
        }
    }

    /// <summary>
    /// 抽象Pizzaクラス (インタフェースクラス)
    /// </summary>
    public interface IPizza
    {
        string GetPizzaName();

        void Prepare();

        void Bake();

        void Cut();

        void Box();
    }

    /// <summary>
    /// 具象Pizzaクラス
    /// </summary>
    public class CheesePizza : IPizza
    {
        public string Name;

        public CheesePizza(string someName)
        {
            this.Name = someName;
        }

        public string GetPizzaName()
        {
            return this.Name;
        }

        public void Prepare()
        {
            Console.WriteLine(this.Name + "ピザの材料を準備します。");
        }

        public void Bake()
        {
            Console.WriteLine(this.Name + "ピザを焼きます。");
        }

        public void Cut()
        {
            Console.WriteLine(this.Name + "ピザをカットします。");
        }

        public void Box()
        {
            Console.WriteLine(this.Name + "ピザを箱に収納します。");
        }
    }

    /// <summary>
    /// 具象Pizzaクラス
    /// </summary>
    public class TomatoPizza : IPizza
    {
        public string Name;

        public TomatoPizza(string someName)
        {
            this.Name = someName;
        }

        public string GetPizzaName()
        {
            return this.Name;
        }

        public void Prepare()
        {
            Console.WriteLine(this.Name + "ピザの材料を準備します。");
        }

        public void Bake()
        {
            Console.WriteLine(this.Name + "ピザを焼きます。");
        }

        public void Cut()
        {
            Console.WriteLine(this.Name + "ピザをカットします。");
        }

        public void Box()
        {
            Console.WriteLine(this.Name + "ピザを箱に収納します。");
        }
    }
}