Simple Factoryパターン

デザインパターンの話が最近仕事でやたら出てくるので

結構忘れているのもあるし理解できていないのもあるので、再度お勉強中です。

まずは簡単な、そしてよく使うSimple Factoryパターンからやってみる。

2つの値を足したり引いたりかけたりわったりしてその計算結果を表示する簡単なサンプルを作ってみます。

上のコードにでてくるCalcModeの定義はこんな感じ。

/// <summary>計算モード</summary>
/// <remarks>factoryクラスで処理を分岐させるための列挙体を定義する</remarks>
public enum CalcMode
{
    /// <summary>足す</summary>
    Add = 0,
    /// <summary>引く</summary>
    Minus = 1,
    /// <summary>かける</summary>
    Multiply = 2,
    /// <summary>割る</summary>
    Divide = 3
}

Factoryクラスはこんな感じ。

public class Factory
{
    /// <summary>コンストラクタ</summary>
    public Factory(){}

    /// <summary>計算処理オブジェクトを生成する</summary>
    /// <param name="mode">計算モード</param>
    /// <returns></returns>
    public AbstractCalculator Create(CalcMode mode) 
    {
        switch (mode)
        {
            case CalcMode.Add:      return new AddCalculator();
            case CalcMode.Minus:    return new MinusCalculator();
            case CalcMode.Multiply: return new MultiplyCalculator();
            case CalcMode.Divide:   return new DivideCalculator();
            default: break;
        }
        throw new NotImplementedException();
    }
}

Factoryクラスで生成するいろんなクラスの基底となる抽象クラスを以下のように定義する。

public abstract class AbstractCalculator
{
    /// <summary>計算する</summary>
    /// <param name="value1"></param>
    /// <param name="value2"></param>
    /// <returns></returns>
    public abstract double Calc(double value1, double value2);
}

あとは派生クラスを定義していく。

/// <summary>足し算を行う計算処理クラス</summary>
public class AddCalculator : AbstractCalculator
{
    /// <summary>コンストラクタ</summary>
    public AddCalculator(){}
    /// <summary>計算する</summary>
    public override double Calc(double value1, double value2)
    {
        return value1 + value2;
    }
}
/// <summary>引き算をする計算処理クラス</summary>
public class MinusCalculator : AbstractCalculator
{
    /// <summary>コンストラクタ</summary>
    public MinusCalculator(){}

    /// <summary>計算する</summary>
    public override double Calc(double value1, double value2)
    {
        return value1 - value2;
    }
}
/// <summary>掛け算をする計算処理クラス</summary>
public class MultiplyCalculator : AbstractCalculator
{
    /// <summary>コンストラクタ</summary>
    public MultiplyCalculator(){}

    /// <summary>計算する</summary>
    public override double Calc(double value1, double value2)
    {
        return value1 * value2;
    }
}
||>

>|cs|
/// <summary>割り算をする計算処理クラス</summary>
public class DivideCalculator : AbstractCalculator
{
    /// <summary>コンストラクタ</summary>
    public DivideCalculator(){}

    /// <summary>計算する</summary>
    public override double Calc(double value1, double value2)
    {
        return value1 / value2;
    }
}

動作確認してみる。

class Program
{
    static void Main(string[] args)
    {
        var calcModes = new List<CalcMode>(){CalcMode.Add, CalcMode.Minus, CalcMode.Multiply, CalcMode.Divide};

        var factory = new Factory();//Factoryクラスを作る

        foreach (var mode in calcModes)
        {
            var calculator = factory.Create(mode);//引数に対応した計算処理クラスを生成する

            double value1 = 50;
            double value2 = 10;

            double result = calculator.Calc(value1, value2);//計算する

            Console.WriteLine("計算結果:" + result.ToString());//結果を表示する
        }
        Console.ReadLine();
    }
}

結果はこーなる。

計算結果:60
計算結果:40
計算結果:500
計算結果:5

Simple Factoryパターンの特徴は

・オブジェクトの生成箇所を一か所で管理できる

・派生クラスがふえてもFactoryクラス内を修正するだけで呼び出し側を修正する必要がない

かなーと思っています。

ちょっと検索してみるとわんくまのまさるさんのブログ

わかりやすく説明されていました。

つまり、「処理のメインとなるクラスに変更を及ぼさない」設計が可能となります。

次はFactory MethodパターンかAbstract Factoryパターンをやってみます。

ちなみにデザインパターンで参考にしている本はこの2つ。

C#デザインパターン

増補改訂版Java言語で学ぶデザインパターン入門