C#

【C#】Factoryとは?具体的にどんなものなのかを説明する【オブジェクト指向】

今回はC#のオブジェクト指向プログラミング「Factory」について説明します。
Factoryとは、その名の通り、「工場」という意味です。

オブジェクトを、生成するだけのクラスです。


オブジェクトを生成するだけって…そんなクラス必要なん??
”ある”と”ない”とでソースの見やすさや管理のしやすさが全然違うよ!

Factoryはインタフェイスに対して、どのオブジェクトを生成するのかを決めます。

前回作成した”ジム会員”のアプリケーションを例にすると…
フリー会員を選択した場合には、フリー会員の割引率を設定。
週1会員を選択した場合には、週1会員の割引率を設定するなど区分によって以降の処理が変化していきます。

つまり、「フリー会員のオブジェクト」を生成するのか、「週2会員のオブジェクトを生成するのか」などを判断がありますよね。
フリー会員を選択している場合は、そのほかのオブジェクトは生成する必要がありません。

全部のオブジェクトを生成してしまっては、余計なメモリーを使用してしまうので処理の性能が劣化してしまいます。
したがって、必要なオブジェクトを必要なときにだけ生成する必要があるのです。

では、どのようにすればそのような実装ができるのか…。
このような時に「Factory」を用意するのです。

実際に実装をして説明しましょう!

前回のインターフェースで使用したアプリケーションを利用します。
まだ用意してない方は前回のインターフェイスの説明を読んでぜひプロジェクトを作ってください。

Factoryを作ってみよう!

まず、Factoryクラスを作成します。
基本的に名前の後ろに「Factoryとつける」ことをお勧めします!

例:●●●Factory.cs

今回はどのクラスオブジェクトを生成するかはアプリケーション内で1つでいいので「static」をつけます。
このように「static」はプログラムが起動されたら、メモリ上にあらかじめ保存しておくので使うタイミングでオブジェクト生成(new)する必要がありません。

「static」はあらかじめメモリーに用意しておくため、何でも「static」にしてしまうと余計な負荷がかかってしまうため、むやみに使用するのは控えましょう!
目安として「アプリケーションで1つしかないもの」に付けるようにしましょう!

■GYMMemberFactory.cs

namespace Interface
{
    public static class GYMMemberFactory 
    {
        //会員区分
        public enum MemberGroup
        {
            Free,
            TwoWeek,
            OneWeek,
        }

        public static IGYMMember Create(MemberGroup mGroup)
        {
            //フリー会員のオブジェクト生成
            if (mGroup == MemberGroup.Free)
            {
                return new FreeMember();
            }

            //週2会員のオブジェクト生成
            if (mGroup == MemberGroup.TwoWeek)
            {
                return new TwoWeekMember();
            }

            //週1会員のオブジェクト生成
            return new OneWeekMember();
        }
    }
}

CreateはGYMMemberを生成するだけのメソッドです。
引数に「会員区分(mGroup)」を与えることで、該当の「会員区分オブジェクト」を生成します。

また今回は会員区分によって分岐させたいので、列挙型(enum)にて区分を設定します。

呼び出し側(Form1)を変更する!

■Form1.cs
列挙体の会員区分をForm1で使用します。
「MemberGroup memberGroup = MemberGroup.Free;」と入力すると、「MemberGroup」に赤い波線が引かれます。
これは、using定義をしなければなりません。

赤い波線にフォーカスを当て「ctrl + .(ドット)」にてusingを追加してください。
列挙体を呼び出す

続いて条件によって区分を設定します。

using System;
using System.Windows.Forms;
using static Interface.GYMMemberFactory;

namespace Interface
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void AnsButton_Click(object sender, EventArgs e)
        {
            //フリー会員:割引率35 %
            //週2会員   :割引率15 %
            //週1会員   :割引率5 %

            //テキストボックスより小計額を取得
            var SumPrice = Convert.ToInt32(PriceTextBox.Text);

            MemberGroup memberGroup = MemberGroup.Free;

            if (OneWeekPlanButton.Checked)
            {
                //週1会員 選択
                memberGroup = MemberGroup.OneWeek;
            }         
            else if (TwoWeekPlanButton.Checked)     
            {
                //週2会員 選択
                memberGroup = MemberGroup.TwoWeek;
            }

            //Factoryより割引率を取得
            IGYMMember gm = GYMMemberFactory.Create(memberGroup);

            PriceLabel.Text = (SumPrice * gm.DiscountRate).ToString() + " 円";
            return;
        }
    }
}


このように、ラジオボタンの操作によって会員区分(MemberGroup)のパラメータを設定し、Factoryに用意したCreateメソッドに会員区分を設定します。
すると、Createメソッドにて区分に対するメンバーオブジェクトを生成します。

これがFactoryです。
Factoryとはこのように、用途によって「対象のオブジェクトを生成するだけ」のクラスです。

実行してみた!

実行結果
このように区分ごとに正しく処理ができていることが分かります。

Factoryを利用することで、アプリケーション全体で処理が散らばらないよう1か所で管理することができます。
このようにFactoryを使用し、役割ごとにソースを分けてプロジェクトを作成することで分かりやすくなります。

バグの抑制や、ソースコードの質を上げるためにも”Factory”は知っておいて損しないです。