抽象ファクトリーパターン
抽象ファクトリーパターン(Abstract Factory Pattern) は、関連するオブジェクト群を生成するためのインターフェースを提供するデザインパターンです。このパターンを使うことで、具体的なクラスに依存することなく、一連の関連するオブジェクトを作成することが可能になります。抽象ファクトリーパターンは、ファクトリーメソッドパターンを拡張したもので、複数の製品ファミリを作成する場合に特に有効です。
このパターンは、複数の製品が相互に関連しており、セットで使う必要がある場合に役立ちます。例えば、GUIアプリケーションで異なるテーマ(ライトモードやダークモード)を切り替えた際に、関連するすべてのコンポーネント(ボタンやテキストフィールドなど)を統一的に作成する必要があるときに使われます。
TypeScriptでの抽象ファクトリーパターンの実装
以下に、TypeScriptで抽象ファクトリーパターンを実装する例を紹介します。この例では、異なるテーマのUIコンポーネント(ボタンとテキストフィールド)を作成します。
GUIコンポーネントの例
typescript
// ボタンインターフェース
interface Button {
render(): void;
}
// テキストフィールドインターフェース
interface TextField {
render(): void;
}
// 抽象ファクトリインターフェース
interface GUIFactory {
createButton(): Button;
createTextField(): TextField;
}
// ライトテーマの具体的なボタンクラス
class LightButton implements Button {
render(): void {
console.log('Rendering a light-themed button');
}
}
// ライトテーマの具体的なテキストフィールドクラス
class LightTextField implements TextField {
render(): void {
console.log('Rendering a light-themed text field');
}
}
// ダークテーマの具体的なボタンクラス
class DarkButton implements Button {
render(): void {
console.log('Rendering a dark-themed button');
}
}
// ダークテーマの具体的なテキストフィールドクラス
class DarkTextField implements TextField {
render(): void {
console.log('Rendering a dark-themed text field');
}
}
// ライトテーマのファクトリクラス
class LightThemeFactory implements GUIFactory {
createButton(): Button {
return new LightButton();
}
createTextField(): TextField {
return new LightTextField();
}
}
// ダークテーマのファクトリクラス
class DarkThemeFactory implements GUIFactory {
createButton(): Button {
return new DarkButton();
}
createTextField(): TextField {
return new DarkTextField();
}
}
// クライアントコード
function renderUI(factory: GUIFactory): void {
const button = factory.createButton();
const textField = factory.createTextField();
button.render();
textField.render();
}
// 実際の使用例
console.log('Using Light Theme:');
const lightFactory = new LightThemeFactory();
renderUI(lightFactory);
console.log('\nUsing Dark Theme:');
const darkFactory = new DarkThemeFactory();
renderUI(darkFactory);
解説
ButtonとTextFieldインターフェース
Button
とTextField
は、それぞれボタンとテキストフィールドを表すインターフェースです。このインターフェースを使うことで、異なるテーマでも共通のメソッド(render
)を持つことを保証します。
GUIFactoryインターフェース(抽象ファクトリ)
GUIFactory
インターフェースは、ボタンとテキストフィールドを作成するためのメソッド(createButton
とcreateTextField
)を定義しています。このインターフェースを実装することで、具体的なファクトリクラスは統一された方法で異なる製品を生成できます。
具体的な製品クラスとファクトリクラス
LightButton
、LightTextField
、DarkButton
、DarkTextField
は、それぞれライトテーマとダークテーマの具体的なUIコンポーネントを表します。LightThemeFactory
とDarkThemeFactory
は、それぞれライトテーマとダークテーマ用のコンポーネントを生成する具体的なファクトリクラスです。
クライアントコード
renderUI
関数は、GUIFactory
インターフェースを使ってUIコンポーネントを生成し、それをレンダリングします。この関数は具体的なテーマには依存せず、ファクトリを通じて生成されるコンポーネントに依存するため、柔軟にテーマを切り替えることができます。
利点
- 一貫性のある製品群の生成: 関連する製品(例えば、同じテーマのボタンとテキストフィールド)を一貫して生成することができます。
- 疎結合の実現: クライアントコードは具体的なクラスに依存しないため、新しいテーマや製品群を追加する際もクライアントコードの変更が最小限で済みます。
- 拡張性の向上: 新しいファクトリや製品を追加することで、既存のコードに影響を与えることなく拡張が可能です。
使用例
- GUIフレームワーク: 異なるテーマ(ライトモード、ダークモードなど)で一貫したUIコンポーネントを生成する場合に使用されます。
- データベースアクセス: 複数のデータベース(例えば、SQLやNoSQL)に対応するクライアントを一貫して生成する場合にも利用されます。
- テスト用のモックオブジェクト生成: さまざまな環境に対応するために、異なる設定のテスト用オブジェクトを生成する場合に有効です。
まとめ
抽象ファクトリーパターンは、関連するオブジェクト群を一貫して生成するためのデザインパターンです。TypeScriptでの実装を通じて、具体的なクラスに依存することなく、一貫性のある製品群を生成する方法を理解しました。
このパターンを利用することで、複数の製品が相互に関連している場合に、それらをまとめて生成し、拡張性と保守性の高い設計を実現することが可能になります。