🤷

TypeScriptで学ぶデザインパターン:Factory Methodパターン

に公開

はじめに

デザインパターンは、ソフトウェア設計において繰り返し発生する問題に対する解決策のテンプレートです。今回はその中でも特に有用な「Factory Methodパターン」をTypeScriptで実装しながら解説します。

Factory Methodパターンとは

Factory Methodパターンは、オブジェクトの生成をサブクラスに委ねることで、クライアントコードと具象クラスの結合を緩和する創造的なデザインパターンです。

基本的な実装

まずはシンプルな例から見ていきましょう。

abstract class Creator {
  public abstract factoryMethod(): Product;

  public someOperation(): string {
    const product = this.factoryMethod();
    return `Creator: ${product.operation()}`;
  }
}

interface Product {
  operation(): string;
}

class ConcreteProductA implements Product {
  public operation(): string {
    return 'ConcreteProductAの操作結果';
  }
}

class ConcreteCreatorA extends Creator {
  public factoryMethod(): Product {
    return new ConcreteProductA();
  }
}

// 使用例
const creator = new ConcreteCreatorA();
console.log(creator.someOperation()); // "Creator: ConcreteProductAの操作結果"

実践的な例:UIコンポーネントの生成

Webアプリケーションでテーマに応じて異なるボタンを生成する例を考えます。

interface Button {
  render(): void;
  onClick(): void;
}

class LightButton implements Button {
  render() {
    console.log('ライトテーマのボタンを表示');
  }

  onClick() {
    console.log('ライトボタンがクリックされました');
  }
}

class DarkButton implements Button {
  render() {
    console.log('ダークテーマのボタンを表示');
  }

  onClick() {
    console.log('ダークボタンがクリックされました');
  }
}

abstract class Dialog {
  public abstract createButton(): Button;

  public render() {
    const button = this.createButton();
    button.render();
    button.onClick();
  }
}

class LightDialog extends Dialog {
  public createButton(): Button {
    return new LightButton();
  }
}

class DarkDialog extends Dialog {
  public createButton(): Button {
    return new DarkButton();
  }
}

// 使用例
const lightDialog = new LightDialog();
lightDialog.render();

const darkDialog = new DarkDialog();
darkDialog.render();

メリットとユースケース

メリット

  1. クライアントコードと具象クラスの結合を弱める
  2. 単一責任の原則を遵守
  3. 開放/閉鎖の原則を遵守

適したユースケース

  • 生成するオブジェクトの型が事前にわからない場合
  • サブクラスが生成するオブジェクトを制御したい場合
  • コードが特定のインターフェースを実装するオブジェクトと連携する場合

まとめ

Factory Methodパターンは、オブジェクト生成の柔軟性を大幅に向上させます。TypeScriptの型システムと組み合わせることで、より安全で拡張可能なコードを書くことができます。次回の開発でオブジェクト生成ロジックが複雑になってきたと感じたら、このパターンの導入を検討してみてください。

参考資料

Discussion