Factory Methodパターンは、オブジェクトの生成方法をサブクラスに委ねることで、柔軟な拡張性を持たせるデザインパターンです。
本記事では、C#を使った具体的なサンプルコードを通じて、Factory Methodパターンの仕組みと実装方法をわかりやすく解説します。
他のプログラミング言語でも応用できるため、オブジェクト指向プログラミングを学ぶすべての開発者に役立つ内容となっています。
Factory Methodパターンとは?
Factory Methodパターンは、オブジェクトの生成をサブクラスに委ねるデザインパターンです。
通常、オブジェクトはnew
キーワードを使って生成しますが、Factory Methodパターンでは、基底クラスでオブジェクトの生成メソッドを定義し、派生クラスで具体的なインスタンスを作成します。
このパターンを使うことで、クライアントコードはどの具体的なクラスが生成されるかを意識せずに、インスタンスを取得できます。
Factory Methodパターンのメリット
Factory Methodパターンを使用することで、以下のようなメリットがあります。
- クラスの依存関係を低減(生成するオブジェクトの型を直接指定しない)
- コードの再利用性が向上(共通のインターフェースを使って柔軟に拡張可能)
- オープン・クローズドの原則(OCP)に準拠(新しいオブジェクトの追加が容易)
基本的な構造
Factory Methodパターンは、以下の4つの要素で構成されます。
- Product(製品クラスのインターフェース)
- 生成されるオブジェクトの共通インターフェースや基底クラス。
- ConcreteProduct(具体的な製品クラス)
Product
を実装した実際のオブジェクト。
- Creator(作成者の基底クラス)
- Factory Methodを定義し、派生クラスでオーバーライドされる。
- ConcreteCreator(具体的な作成者クラス)
Creator
を継承し、具体的なオブジェクトを生成するクラス。
+------------------+
| IProduct | ← Product(製品インターフェース)
+------------------+
| + Use() |
+------------------+
▲
│
+------------------+ +------------------+
| ProductA | | ProductB | ← ConcreteProduct(具体的な製品)
+------------------+ +------------------+
| + Use() | | + Use() |
+------------------+ +------------------+
+------------------+
| Creator | ← Creator(作成者の基底クラス)
+------------------+
| + CreateProduct() |
| + SomeOperation() |
+------------------+
▲
│
+------------------+ +------------------+
| ConcreteCreatorA | | ConcreteCreatorB | ← ConcreteCreator(具体的な作成者)
+------------------+ +------------------+
| + CreateProduct() |
+------------------+
C#での実装例
C#を使ったFactory Methodパターンの実装を紹介します。
(1) 製品の共通インターフェース(Product)
// 製品の共通インターフェース
public interface IProduct
{
void Use();
}
(2) 具体的な製品クラス(ConcreteProduct)
// 具体的な製品クラスA
public class ProductA : IProduct
{
public void Use()
{
Console.WriteLine("ProductAを使用しています。");
}
}
// 具体的な製品クラスB
public class ProductB : IProduct
{
public void Use()
{
Console.WriteLine("ProductBを使用しています。");
}
}
(3) クリエイタークラス(Creator)
// クリエイターの基底クラス
public abstract class Creator
{
// Factory Method: サブクラスでオーバーライドする
public abstract IProduct CreateProduct();
// Factory Methodを利用する共通処理
public void SomeOperation()
{
var product = CreateProduct();
product.Use();
}
}
(4) 具体的なクリエイタークラス(ConcreteCreator)
// 具体的なクリエイターA
public class ConcreteCreatorA : Creator
{
public override IProduct CreateProduct()
{
return new ProductA();
}
}
// 具体的なクリエイターB
public class ConcreteCreatorB : Creator
{
public override IProduct CreateProduct()
{
return new ProductB();
}
}
(5) クライアントコード
class Program
{
static void Main()
{
// ConcreteCreatorAを使用
Creator creatorA = new ConcreteCreatorA();
creatorA.SomeOperation(); // "ProductAを使用しています。" と表示
// ConcreteCreatorBを使用
Creator creatorB = new ConcreteCreatorB();
creatorB.SomeOperation(); // "ProductBを使用しています。" と表示
}
}
解説
IProduct
インターフェースUse()
メソッドを定義し、共通の機能を提供。
ProductA
とProductB
クラスIProduct
を実装し、それぞれ異なる動作を提供。
Creator
クラス(基底クラス)CreateProduct()
メソッドを定義し、サブクラスでオーバーライドする仕組みを作る。SomeOperation()
メソッドを持ち、生成されたオブジェクトを使用する共通の処理を定義。
ConcreteCreatorA
とConcreteCreatorB
クラス(サブクラス)CreateProduct()
メソッドをオーバーライドし、それぞれProductA
とProductB
を生成。
Program
クラス(クライアントコード)ConcreteCreatorA
またはConcreteCreatorB
を使用し、適切なProduct
インスタンスを生成・使用する。
この構造を活用することで、新しい Product
クラスを追加する際に、Creator
クラスを修正せずに済みます。
拡張性が高く、柔軟な設計を実現できます!
Factory Methodパターンの活用例
Factory Methodパターンは、次のような場面で有効に活用できます。
- データベースアクセスの抽象化(異なるDBに対応するクラスを切り替え)
- GUIコンポーネントの生成(異なるプラットフォームごとに適切なUIを提供)
- ゲーム開発(敵キャラクターの種類ごとに異なるインスタンスを生成)
まとめ
Factory Methodパターンのポイントを整理すると、以下のようになります。
- オブジェクトの生成をサブクラスに任せることで、依存関係を低減
- 新しいクラスの追加が容易になり、拡張性が向上
- インターフェースを用いることで、柔軟な設計が可能
- さまざまなシステム開発に応用できる
Factory Methodパターンは、オブジェクト指向プログラミングの基本を理解するうえで非常に重要なデザインパターンのひとつです。特に、オブジェクトの生成を管理しやすくなるため、拡張性のあるシステムを作る際に役立ちます。
C#以外の言語でも応用できるので、実際にコードを書いて試してみてください。Factory Methodパターンを活用することで、より柔軟でメンテナブルなプログラムを作成できるようになるでしょう!