📌
デザインパターンを学ぶ #21 アブストラクトファクトリー(Abstract Factory)
1. はじめに
今回は Abstract Factory(アブストラクトファクトリー)パターン。
目的は、関連するオブジェクト群を「組み合わせ単位」で生成する仕組みをまとめることです。
「同じ系統のオブジェクトを一貫性をもって作りたい」ときに役立ちます。
GUIライブラリで「Windows用の部品」と「Mac用の部品」を切り替える例が典型です。
2. Abstract Factoryとは?
登場する役割は以下の通りです:
- AbstractFactory … 製品群を生成するインターフェース
- ConcreteFactory … 実際に製品群を生成する工場
- AbstractProduct … 製品の抽象インターフェース
- ConcreteProduct … 具体的な製品
- Client … 工場を通じて製品群を利用する
ポイントは、**「工場を切り替えるだけで、関連する製品群を一括で差し替えできる」**ことです。
3. 実装イメージ(PHP)
<?php
// Abstract Products
interface Button {
public function render(): string;
}
interface Checkbox {
public function check(): string;
}
// Concrete Products (Windows)
class WindowsButton implements Button {
public function render(): string { return "Windows風ボタン"; }
}
class WindowsCheckbox implements Checkbox {
public function check(): string { return "Windows風チェックボックス"; }
}
// Concrete Products (Mac)
class MacButton implements Button {
public function render(): string { return "Mac風ボタン"; }
}
class MacCheckbox implements Checkbox {
public function check(): string { return "Mac風チェックボックス"; }
}
// Abstract Factory
interface GUIFactory {
public function createButton(): Button;
public function createCheckbox(): Checkbox;
}
// Concrete Factories
class WindowsFactory implements GUIFactory {
public function createButton(): Button { return new WindowsButton(); }
public function createCheckbox(): Checkbox { return new WindowsCheckbox(); }
}
class MacFactory implements GUIFactory {
public function createButton(): Button { return new MacButton(); }
public function createCheckbox(): Checkbox { return new MacCheckbox(); }
}
// Client
class Application {
private Button $button;
private Checkbox $checkbox;
public function __construct(GUIFactory $factory) {
$this->button = $factory->createButton();
$this->checkbox = $factory->createCheckbox();
}
public function renderUI(): void {
echo $this->button->render() . PHP_EOL;
echo $this->checkbox->check() . PHP_EOL;
}
}
// --- 実行例 ---
$app = new Application(new WindowsFactory());
$app->renderUI();
// Windows風ボタン
// Windows風チェックボックス
$app = new Application(new MacFactory());
$app->renderUI();
// Mac風ボタン
// Mac風チェックボックス
4. メリット・デメリット
メリット
- 製品群の一貫性を保証できる
- 工場を切り替えるだけで環境に応じた実装を利用できる
- 依存を抽象に寄せるのでテストや拡張が容易
デメリット
- クラスやインターフェースの数が増える
- 小規模ではオーバーエンジニアリングになりやすい
5. 使いどころ
- プラットフォームごとにUI部品を変えたいとき(Windows / Mac / Linux)
- DBドライバや外部サービスの実装を切り替えるとき
- 製品群の一貫性を守りつつ差し替えたいとき
「関連するオブジェクトをまとめて差し替える」のがキーワードです。
Discussion