JavaScriptデザインパターン入門

## 1. はじめに

JavaScriptデザインパターンは、JavaScriptを使ってプログラムを書くときによく出くわす問題を解決するためのガイドです。これらのパターンの背後にある考え方を理解することで、自分の問題に適用することができます。また、これらのパターンが自分のコードに役立つ場合を見つけることもできます。

## 2. モジュールパターン

モジュールパターンは、JavaScriptのモジュールシステムの一部で、データを保護する方法を提供します。これは、モジュール内のプライベートなデータと動作を保護し、一方で公開APIを提供する方法です。これにより、プライベートとパブリックのアクセスレベルを持つ自己完結型のモジュールオブジェクトを作成することができます。

これは、JavaやC++のような言語でクラスにアクセス修飾子を使用するのに似ています。

JavaScriptでは、クロージャを使用してモジュールパターンを実装することができます。

クロージャを使用してプライベートメンバー（関数、変数、データ）を包むことで、これらのメンバーがアクセス可能な範囲を作り出し、外部の世界から直接公開されることなく、内部の詳細を隠すことができます。

さらに、クロージャから公開APIを返すことで、モジュールのインターフェースの一部として公開したい特定の関数やプロパティへのプライベートアクセスを可能にします。

これにより、モジュールのどの部分が他のコードベースの部分にアクセス可能であるかを制御することができます。これにより、公開機能とプライベート機能の間に明確な境界が保たれます。

### モジュールパターンのサンプルコード

```typescript
interface Item {
  name: string;
  quantity: number;
}

const ShoppingCartModule = (function () {
  // プライベートデータ
  let cartItems: Item[] = [];

  // プライベートメソッド
  function calculateTotalItems(): number {
    return cartItems.reduce((total, item) => total + item.quantity, 0);
  }

  // パブリックAPI
  return {
    addItem(item: Item) {
      cartItems.push(item);
    },

    getTotalItems(): number {
      return calculateTotalItems();
    },

    clearCart() {
      cartItems = [];
    }
  };
})();

// 使用例
ShoppingCartModule.addItem({ name: 'Product 1', quantity: 2 });
ShoppingCartModule.addItem({ name: 'Product 2', quantity: 1 });

console.log(ShoppingCartModule.getTotalItems()); // 出力: 3

ShoppingCartModule.clearCart();
console.log(ShoppingCartModule.getTotalItems()); // 出力: 0
```

このコードでは、`ShoppingCartModule`という名前のモジュールを作成しています。このモジュールは、ショッピングカートの機能を提供します。モジュール内部では、`cartItems`という名前のプライベートな配列を持っており、これがショッピングカート内のアイテムを保持します。また、`calculateTotalItems`という名前のプライベートな関数を持っており、これがショッピングカート内のアイテムの合計数を計算します。

公開APIとしては、`addItem`、`getTotalItems`、`clearCart`という3つの関数を提供しています。`addItem`関数は、アイテムをショッピングカートに追加します。`getTotalItems`関数は、ショッピングカート内のアイテムの合計数を取得します。`clearCart`関数は、ショッピングカートを空にします。

このコードを実行すると、まず`Product 1`と`Product 2`という2つのアイテムがショッピングカートに追加されます。その後、ショッピングカート内のアイテムの合計数がコンソールに出力されます。最後に、ショッピングカートが空にされ、再度ショッピングカート内のアイテムの合計数がコンソールに出力されます。


## 3. オブザーバーパターン

オブザーバーパターンは、オブジェクト間に一対多の依存関係を作ります。一つのオブジェクトの状態が変わると、それに依存しているすべてのオブジェクトに通知し、それらは自動的に更新され

ます。このパターンは、イベント駆動のインタラクションを管理したり、システム内のコンポーネントを分離したりするのに特に役立ちます。

JavaScriptでは、組み込みの`addEventListener`、`dispatchEvent`メソッド、または任意のイベント処理メカニズムを使用してオブザーバーパターンを実装することができます。オブザーバーをイベントやサブジェクトに登録することで、特定のイベントが発生したときにそれらを通知し、更新することができます。

### オブザーバーパターンのサンプルコード

```typescript
interface Subscriber {
  name: string;
  receiveNotification: (message: string) => void;
}

class NotificationSystem {
  // List of subscribers
  private subscribers: Subscriber[] = [];

  // Method to subscribe to notifications
  subscribe(subscriber: Subscriber) {
    this.subscribers.push(subscriber);
  }

  // Method to unsubscribe from notifications
  unsubscribe(subscriber: Subscriber) {
    const index = this.subscribers.indexOf(subscriber);

    if (index !== -1) {
      this.subscribers.splice(index, 1);
    }
  }

  // Method to notify subscribers
  notify(message: string) {
    this.subscribers.forEach(function (subscriber) {
      subscriber.receiveNotification(message);
    });
  }
}

class SubscriberClass implements Subscriber {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  // Method to receive and handle notifications
  receiveNotification(message: string) {
    console.log(this.name + ' received notification: ' + message);
  }
}

// Usage example
const notificationSystem = new NotificationSystem();

// Create subscribers
const subscriber1 = new SubscriberClass('Subscriber 1');
const subscriber2 = new SubscriberClass('Subscriber 2');

// Subscribe subscribers to the notification system
notificationSystem.subscribe(subscriber1);
notificationSystem.subscribe(subscriber2);

// Notify subscribers
notificationSystem.notify('New notification!');
```

このコードでは、`NotificationSystem`という名前の通知システムを作成しています。この通知システムは、通知を送信するシステムを表しています。また、`Subscriber`という名前の購読者を作成しています。これらの購読者は、通知の受信者を表しています。

`NotificationSystem`には、通知を受け取りたい購読者を格納する`subscribers`という名前の配列があります。`subscribe`メソッドを使って購読者が自分自身を`subscribers`配列に追加することで登録できます。`unsubscribe`メソッドを使って購読者が`subscribers`配列から自分自身を削除することで登録を解除できます。

`NotificationSystem`の`notify`メソッドは、`subscribers`配列をイテレートし、各購読者の`receiveNotification`メソッドを呼び出します。これにより、購読者は通知を受け取り、それを処理することができます。

`Subscriber`関数のインスタンスは購読者を表しています。各購読者は、`receiveNotification`メソッドを持っており、これにより受け取った通知をどのように処理するかを決定します。この例では、メソッドは受け取ったメッセージをコンソールに出力します。

オブザーバーパターンを使用するには、まず`NotificationSystem`のインスタンスを作成します。次に、`Subscriber`のインスタンスを作成し、それらを`subscribe`メソッドを使って通知システムに追加します。

通知を送信すると、各購読者の`receiveNotification`メソッドがトリガーされ、各購読者のメッセージがログに記録されます。

オブザーバーパターンにより、通知システムと購読者の間に疎結合が可能となり、柔軟性が向上します。このパターンは、イベント駆動システムのメンテナンスを容易にするための関心の分離を推進します。

## まとめ
この記事では、JavaScriptのデザインパターンの基本的な2つ、モジュールパターンとオブザーバーパターンについて説明しました。

モジュールパターンは、データと動作をカプセル化し、公開APIを提供することで、プライベートとパブリックのアクセスレベルを持つ自己完結型のモジュールオブジェクトを作成する方法を提供します。これにより、コードの組織化とデータのプライバシーが向上します。

一方、オブザーバーパターンは、オブジェクト間に一対多の依存関係を作り、一つのオブジェクトの状態が変わると、それに依存しているすべてのオブジェクトに通知し、それらは自動的に更新されます。これにより、イベント駆動のインタラクションを管理したり、システム内のコンポーネントを分離したりするのに特に役立ちます。

これらのデザインパターンを理解し、適切に使用することで、より効率的で保守性の高いJavaScriptコードを書くことができます。ただし、これらのパターンを適用する際には、パフォーマンスへの影響、アンチパターンの回避、コーディング規約の遵守など、いくつかの注意点を念頭に置くことが重要です。


## 続き
[JavaScriptデザインパターン入門【ファクトリパターン】](https://qiita.com/itinerant_programmer/items/0b92508d067f2c3d12ca)