ファクトリパターンを学んでいると、「Factory Methodパターン」と「Abstract Factoryパターン」の違いがわかりにくいと感じる方は少なくないでしょう。
さらに「Simple Factory」も加わると、それぞれの関係性と使い分けの基準がよりわかりにくくなります。
本記事では、Simple Factory・Factory Method・Abstract Factoryの三つの違いを体系的に整理し、それぞれの特徴・構造・適した使用場面を詳しく解説します。
どのパターンを選ぶべきか迷っているエンジニアの方に、明確な判断基準を提供できる内容となっています。
それぞれのパターンを正しく理解して、適切な場面で使い分けられるようになりましょう。
Simple Factory・Factory Method・Abstract Factoryの本質的な違い
それではまず、三つのファクトリパターンの本質的な違いと基本構造について解説していきます。
三つのパターンはいずれも「オブジェクト生成の分離」という共通のゴールを持ちますが、その実現方法と対応する問題の複雑さが異なります。
この違いを明確に理解することが、適切なパターン選択の出発点となります。
Simple Factoryの特徴と位置づけ
Simple Factoryは、厳密にはGoFの23のデザインパターンには含まれていませんが、実務では非常によく使われるシンプルなファクトリの実装形態です。
Simple Factoryの特徴は、静的メソッドまたは専用クラスが引数に基づいて生成するオブジェクトを決定するシンプルな構造にあります。
継承・多態性を使わず、if-elseやswitch文で生成クラスを切り替えるため、実装が容易で理解しやすいという利点があります。
一方、新しい製品を追加する際はFactory自体を修正する必要があるため、OCPには違反します。
「まず動くものを作りたい」「生成するクラスの種類が少なく増加の見込みもない」という場面に向いている実用的な手法です。
Factory Methodパターンの特徴:継承による拡張
Factory MethodパターンはGoFの正式なデザインパターンであり、継承(サブクラス化)によって生成するオブジェクトの種類を拡張するパターンです。
抽象Creatorクラスでファクトリメソッドを定義し、ConcreteCreatorサブクラスでその実装(どの具体クラスを生成するか)を決定します。
新しい製品を追加する際は、新しいConcreteProductクラスと対応するConcreteCreatorクラスを追加するだけで済み、既存コードへの修正は不要です。
これにより、OCPを満たした拡張が実現できます。
ただし、製品が1種類(単一の製品インターフェース)に限定されるため、複数の関連する製品群を一貫して管理するには限界があります。
Abstract Factoryパターンの特徴:複数製品群の管理
Abstract Factoryパターンは、関連する複数の製品を一貫したセットとして生成するためのインターフェースを提供するパターンです。
| 項目 | Simple Factory | Factory Method | Abstract Factory |
|---|---|---|---|
| GoFパターン | 非公式 | 公式(生成パターン) | 公式(生成パターン) |
| 拡張方法 | Factoryを修正 | サブクラスを追加 | 新Factoryを追加 |
| 管理できる製品数 | 1種類 | 1種類 | 複数種類(製品群) |
| 実装の複雑さ | 低 | 中 | 高 |
| OCPへの準拠 | 違反しやすい | 準拠 | 準拠(製品追加は困難) |
Abstract Factoryでは、一つのファクトリインターフェースが複数のCreateメソッドを持ち、関連する製品ファミリー全体の生成を担当します。
ファクトリを切り替えるだけで、関連する製品群すべてを一括して差し替えることができる点が最大の強みです。
Factory Methodと抽象ファクトリパターンの構造的な違い
続いては、Factory MethodとAbstract Factoryの構造的な違いをより詳しく確認していきます。
二つのパターンは名前が似ているため混同されやすいですが、解決する問題と設計構造には明確な違いがあります。
継承の使い方と製品の数の違いが、二つのパターンを区別する最も重要なポイントです。
継承関係の違い:縦の拡張と横の拡張
Factory MethodパターンとAbstract Factoryパターンの最も根本的な構造的違いは、拡張の方向性にあります。
Factory Methodは「縦の拡張」であり、Creatorクラスを継承した新しいConcreteCreatorサブクラスを追加することで、生成する製品の種類を拡張します。
クラス階層が縦(継承方向)に伸びていくイメージです。
Abstract Factoryは「横の拡張」であり、新しい製品ファミリーを追加する場合は新しい具体ファクトリクラスを追加します。
ただし、Abstract Factoryに新しい製品の種類(新しいCreateメソッド)を追加する場合は、すべての具体ファクトリクラスを修正する必要があり、これはAbstract Factoryのトレードオフです。
単一製品と複数製品群の違い
Factory Methodは基本的に一種類の製品インターフェースに対して動作するパターンです。
一つのCreatorが一種類のProductを生成するという1対1の関係が基本構造となります。
Abstract Factoryは複数種類の関連製品をセットで生成するパターンであり、一つのFactoryが複数種類のProductを生成する1対多の関係が基本構造です。
Factory MethodとAbstract Factoryの使い分けの決め手は「生成するオブジェクトが何種類あるか」です。単一の製品ファミリーならFactory Method、複数の関連製品をセットで管理する必要があればAbstract Factoryを選択するのが基本的な判断基準です。
具体的な設計例での比較
データベース接続を例に、Factory MethodとAbstract Factoryの違いを具体的に比較してみましょう。
Factory Methodによるデータベース接続の例:
// 一種類の製品(接続オブジェクト)だけを管理
abstract class DBConnector {
abstract Connection createConnection();
}
class MySQLConnector extends DBConnector {
Connection createConnection() { return new MySQLConnection(); }
}
Abstract Factoryによるデータベース関連オブジェクト群の例:
// 複数の関連製品(接続・クエリ・トランザクション)をセットで管理
interface DBFactory {
Connection createConnection();
QueryBuilder createQueryBuilder();
Transaction createTransaction();
}
class MySQLFactory implements DBFactory {
public Connection createConnection() { return new MySQLConnection(); }
public QueryBuilder createQueryBuilder() { return new MySQLQueryBuilder(); }
public Transaction createTransaction() { return new MySQLTransaction(); }
}
Abstract Factoryを使用する場合、MySQLからPostgreSQLへの切り替えはMySQLFactoryをPostgreSQLFactoryに差し替えるだけで完結し、Connection・QueryBuilder・Transactionすべてが一括して切り替わります。
三つのパターンの使い分けと選択基準
続いては、三つのパターンを実際にどのような基準で使い分けるかを確認していきます。
適切なパターン選択は、プロジェクトの要件・規模・拡張性の見通しに基づいた総合的な判断が必要です。
実務で役立つ具体的な判断フローをご紹介します。
パターン選択のためのフローチャート的判断基準
三つのパターンのどれを使うべきかは、以下の判断基準で整理することができます。
パターン選択の判断フロー:
Q1:生成するオブジェクトの種類が今後増える可能性はありますか?
→ いいえ:Simple Factoryで十分
→ はい:Q2へ
Q2:生成するオブジェクトは1種類の製品インターフェースに収まりますか?
→ はい:Factory Methodパターンを採用
→ いいえ:Q3へ
Q3:複数の関連製品をセットで切り替える必要がありますか?
→ はい:Abstract Factoryパターンを採用
→ いいえ:Factory Methodを複数組み合わせることを検討
この判断フローを参考にしながら、具体的なプロジェクト要件に当てはめて最適なパターンを選択しましょう。
実際のフレームワーク・ライブラリでの活用例
三つのパターンは実際のフレームワークやライブラリの内部でも多く使われています。
JavaのJDBC(java.sql.DriverManager)はSimple Factoryに近い形でデータベース接続オブジェクトを生成します。
SpringフレームワークのBeanFactoryはFactory Methodパターンを活用しており、設定に基づいてBeanオブジェクトを生成します。
Abstract Factoryの代表例としては、JavaのAWTにおけるToolkitクラスが挙げられ、プラットフォームに応じた関連UIコンポーネントのセットを生成します。
実際のフレームワークの設計を分析することで、各パターンの実践的な使いどころをより深く理解することができます。
パターンの組み合わせと発展的な活用
実際のソフトウェア設計では、ファクトリパターンを単独で使用するだけでなく、他のデザインパターンと組み合わせることもよくあります。
Abstract FactoryとSingletonパターンを組み合わせることで、アプリケーション全体で一つのファクトリインスタンスを共有し、一貫した製品生成を実現することができます。
Factory MethodとTemplate Methodパターンを組み合わせることで、生成後の初期化処理や共通処理をCreatorクラスに集約した高凝集な設計が実現できます。
パターンの組み合わせ方を理解することで、より複雑な設計課題に対応できる応用力が養われます。
まとめ
本記事では、Simple Factory・Factory Method・Abstract Factoryの三つのパターンの違い、構造的特徴、そして使い分けの基準を詳しく解説しました。
Simple Factoryはシンプルで実装コストが低く、Factory Methodは継承による柔軟な拡張を実現し、Abstract Factoryは複数の関連製品群を一貫して管理する最も強力なパターンです。
「生成する製品の種類が増えるか」「複数の関連製品をセットで管理するか」という判断基準を軸に、プロジェクト要件に最適なパターンを選択することが重要です。
実際のフレームワークの設計にも多く採用されているこれらのパターンを深く理解することで、設計力が大幅に向上するでしょう。