設計マジでヤバいマンなので、デザインパターンをちゃんと勉強することにした。
以降、このシリーズ(続くかどうかはおいといて)基本的に(ブログにアウトプットすることで継続するという意味も込めた)自分向けのメモ。

目次

  1. ダラダラしたまえがきとか
  2. 概要
  3. コード
    1. インターフェース
    2. 具象クラス
    3. 列挙体
    4. Factoryクラス
    5. メリット
    6. デメリット
  4. 参考サイト

ダラダラしたまえがきとか


恥ずかしながら碌にコードの設計っていうのを知らない。
これは前職で保守してたコードが1mmも勉強にならない、ありとあらゆるアンチパターンを詰め込んだようなコードだったため主に実務で全くまともな技術が身につかなかったのが一番大きいと思ってる。
この辺の愚痴を書きたい気持ちもあるものの書いても仕方ない&本筋から逸れるので今回は書かないとして、設計ヤバいと思った私は1年半前くらいにデザインパターンを勉強することにした。

が、挫折した…
なんとなく理屈はわかるものの(←こういうのは大抵わかってない)既存の秘伝のコードにどう適用してよいかわからず困り果てた。
加えて、当時私はVB.NETしか経験がなく、著名な本はだいたいJavaで記述されており、コードを読むのに苦労した。(VB.NETでそれも static & グローバル祭りなコードしか経験ない人間にはこれは相当ハードルが高かった。)

そこで、私はまずコード(Java)を読むことのハードルを下げることを目標にした。
しかし、Javaの開発環境を準備するのは正直手間だった(当時かなり多忙で余裕がなかった)ので、同じVisualStudioで開発できて、かつ文法も似ているC#を勉強することにした。

そうして、学習意欲が「WPF + MVVM」とかに逸れたりして、デザインパターンほったらかしで、今ではC#とWPFが好きです。
という話はどうでもいいや。

長くなったけど、本筋に戻ります。

概要


「Simple Factory」は「Abstract Factory」とは違う。
使用するクラスを容易に切り替えるための「Abstract Factory」の簡易版である。
インスタンスの生成を「Factory」クラスに任せる。

コード


サンプルは異なる楽器クラスを生成するものにします。

インターフェース

まず、インターフェース作ります。
インターフェースには各具象クラスで実装するメソッドを記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// <summary>
/// 楽器のインターフェースです。
/// </summary>
public interface IInstrument
{
/// <summary>
/// 持ち運び可能かどうか。
/// </summary>
bool CanPortable();

/// <summary>
/// 楽器を鳴らします。
/// </summary>
string Play();
}

具象クラス

前述のインターフェースを継承するクラスを作ります。
今回はピアノクラスとフルートクラス。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/// <summary>
/// ピアノクラス
/// </summary>
public class Piano : IInstrument
{
public bool CanPortable()
{

return false;
}

public string Play()
{

return("ポロローン");
}
}

/// <summary>
/// フルートクラス
/// </summary>
public class Flute : IInstrument
{
public bool CanPortable()
{

return true;
}

public string Play()
{

return ("ピーピー");
}
}

列挙体

Factoryクラスの前に…
個人的にあんまり文字列渡して判定とかは好きでないので列挙体を作ります。

1
2
3
4
5
public enum InstrumentEnum
{
Piano = 0,
Flute = 1
}

Factoryクラス

引数をもとに生成するクラスを切り替えるクラスです。
先ほどの列挙体でわけるようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// 具象クラスのインスタンスを生成するFactoryクラスです。
/// </summary>
public class InstrumentFactory
{
/// <summary>
/// 楽器を生成します
/// </summary>
public IInstrument CreateInstrument(Instrument.InstrumentEnum instrument)
{

switch(instrument)
{
case Instrument.InstrumentEnum.Piano:
return new Instrument.Piano();
case Instrument.InstrumentEnum.Flute:
return new Instrument.Flute();
default:
throw new ArgumentException();
}
}
}

以上。
で、あとは実行するのみ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Program
{
//Factoryクラスのインスタンスを生成
private static InstrumentFactory _instrumentFactory = new InstrumentFactory();

static void Main(string[] args)
{

//作成したインターフェースの型
IInstrument _instrument;

//ピアノ生成(ピアノクラスのインスタンスはFactoryクラス内で生成される。)
_instrument = _instrumentFactory.CreateInstrument(Instrument.InstrumentEnum.Piano);
System.Console.WriteLine(_instrument.Play());
System.Console.WriteLine(_instrument.CanPortable() == true ? "持ち運べます。" : "持ち運べません!");

//フルート生成(フルートクラスのインスタンスはFactoryクラス内で生成される。)
_instrument = _instrumentFactory.CreateInstrument(Instrument.InstrumentEnum.Flute);
System.Console.WriteLine(_instrument.Play());
System.Console.WriteLine(_instrument.CanPortable() == true ? "持ち運べます。" : "持ち運べません!");

System.Console.ReadLine();
}
}

実行結果は以下のようになります。

1
2
3
4
ポロローン
持ち運べません!
ピーピー
持ち運べます。

メリット

  • クラスの生成個所を一か所で管理できるので、具象クラスが増えてもFactoryクラスに記述追加するだけでよい。

デメリット

  • クラスが増えれば増えるほどFactoryクラスの条件分岐が増える。

参考サイト

デザインパターンを学ぶ~その14:Factoryパターン(1)~