DP-01: Abstract Factory パターン
関連するオブジェクト族(ファミリー)をまとめて生成するインターフェースを提供するパターンです。 データベース接続のように「MySQL 用部品一式」「PostgreSQL 用部品一式」を切り替える場面でよく使われます。
Abstract Factory パターンとは
Abstract Factory(抽象ファクトリー)パターンは、関連する複数のオブジェクトを一まとまりで生成するための インターフェースを定義するパターンです。具体的なクラス名を直接書かずに、オブジェクト群を作成できます。
Abstract Factory パターンの特徴
- 製品ファミリーの一貫性: MySQL 用の Connection と Statement は必ず MySQL 版が返るため、組み合わせミスが起きない
- 切り替えの容易さ: ファクトリーを差し替えるだけで、クライアントコードを変えずに実装を変えられる
- 依存関係の逆転: クライアントは抽象インターフェースだけに依存し、具体クラスを知らなくてよい
Factory Method との違い
- Factory Method: 1種類のオブジェクトを生成するメソッドをサブクラスで実装する
- Abstract Factory: 複数種類の関連オブジェクト(製品ファミリー)をまとめて生成するインターフェースを定義する
サンプルコード
Java 8 では interface と static な内部クラスで抽象ファクトリーを実装します。クライアントコード(runDbOperation メソッド)は DbFactory インターフェースだけに依存しており、MySQL と PostgreSQL のどちらを渡しても同じコードで動作します。
よくあるミス・注意点
⚠️ 新しい製品を追加するとすべてのファクトリーを修正する必要がある
Abstract Factory インターフェースに新メソッドを追加すると、 すべての具体ファクトリークラス(MySqlFactory、PostgreSqlFactory など)を修正しなければなりません。 製品の種類が頻繁に増える場合は設計を見直しましょう。
⚠️ Factory Method と混同してしまう
Factory Method は「1種類のオブジェクトをサブクラスで作り分ける」パターンです。 Abstract Factory は「複数の関連オブジェクトをまとめて作る」パターンです。 1つのメソッドしかない Abstract Factory は Factory Method と同じになってしまうため、 複数の製品を一貫して生成する場面で選択しましょう。
⚠️ クライアントコードで具体クラスを直接使ってしまう
new MySqlConnection() のように具体クラスを直接インスタンス化すると、 Abstract Factory パターンの恩恵がなくなります。 クライアントコードは必ず抽象インターフェース(DbFactory、DbConnection など)だけを参照するようにしましょう。
テストする観点
- MySqlFactory が返す Connection は MySQL 用の接続文字列を含むこと
- PostgreSqlFactory が返す Connection は PostgreSQL 用の接続文字列を含むこと
- MySqlFactory が返す Statement は MySQL 用の SQL 実行メッセージを返すこと
- 同じファクトリーから生成した Connection と Statement は同じ DB 種別(製品ファミリーの一貫性)であること
- クライアントコード(runDbOperation)は DbFactory インターフェースを受け取るため、MySqlFactory と PostgreSqlFactory のどちらでも正常動作すること(ポリモーフィズムの確認)
- executeQuery に null を渡したとき NullPointerException が発生しないこと(境界値)