1. はじめに
JavaScriptデザインパターンは、JavaScriptを使ってプログラムを書くときによく出くわす問題を解決するためのガイドです。これらのパターンの背後にある考え方を理解することで、自分の問題に適用することができます。また、これらのパターンが自分のコードに役立つ場合を見つけることもできます。
2. モジュールパターン
モジュールパターンは、JavaScriptのモジュールシステムの一部で、データを保護する方法を提供します。これは、モジュール内のプライベートなデータと動作を保護し、一方で公開APIを提供する方法です。これにより、プライベートとパブリックのアクセスレベルを持つ自己完結型のモジュールオブジェクトを作成することができます。
これは、JavaやC++のような言語でクラスにアクセス修飾子を使用するのに似ています。
JavaScriptでは、クロージャを使用してモジュールパターンを実装することができます。
クロージャを使用してプライベートメンバー(関数、変数、データ)を包むことで、これらのメンバーがアクセス可能な範囲を作り出し、外部の世界から直接公開されることなく、内部の詳細を隠すことができます。
さらに、クロージャから公開APIを返すことで、モジュールのインターフェースの一部として公開したい特定の関数やプロパティへのプライベートアクセスを可能にします。
これにより、モジュールのどの部分が他のコードベースの部分にアクセス可能であるかを制御することができます。これにより、公開機能とプライベート機能の間に明確な境界が保たれます。
モジュールパターンのサンプルコード
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
メソッド、または任意のイベント処理メカニズムを使用してオブザーバーパターンを実装することができます。オブザーバーをイベントやサブジェクトに登録することで、特定のイベントが発生したときにそれらを通知し、更新することができます。
オブザーバーパターンのサンプルコード
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コードを書くことができます。ただし、これらのパターンを適用する際には、パフォーマンスへの影響、アンチパターンの回避、コーディング規約の遵守など、いくつかの注意点を念頭に置くことが重要です。