ちゃんなるぶろぐ

エンジニア5年生🧑‍💻 オライリーとにらめっこする毎日。

【5分でわかる!】TypeScriptでDesign Pattern〜Bridge Pattern〜

どうも、ちゃんなるです!

今回は、Bridge Patternを紹介します🖐️

概要

Bridge Patternは、機能実装を分離して拡張しやすくするデザインパターンです。

今回示すサンプルプログラムの設計

メッセージ送信アプリを例とし、様々なプラットフォーム(SMS、Eメール、Slack)で送信できるように、Bridge Patternを使ってみましょう✉️

送信するメッセージをコンソールに出力します💻

機能が「MessageSenderクラス」と、それを拡張する「TextMessage」や「RichMessage」クラスを指し、実装が「MessageSendingImplementationインターフェース」と、それを実装する「SmsSender」や「EmailSender」クラスを指します。

サンプルコード

まず、抽象クラスと具象クラスを定義します。

abstract class MessageSender {
  constructor(protected implementation: MessageSendingImplementation) {}
  abstract send(message: string): void;
}

interface MessageSendingImplementation {
  sendMessage(message: string): void;
}

class SmsSender implements MessageSendingImplementation {
  sendMessage(message: string): void {
    console.log(`【SMS送信】${message}`);
  }
}

class EmailSender implements MessageSendingImplementation {
  sendMessage(message: string): void {
    console.log(`【Eメール送信】${message}`);
  }
}

メッセージの種類によって機能を拡張します。

class TextMessage extends MessageSender {
  send(message: string): void {
    this.implementation.sendMessage(`テキストメッセージ送信: ${message}`);
  }
}

class RichMessage extends MessageSender {
  send(message: string): void {
    this.implementation.sendMessage(`リッチメッセージ送信: ***${message}***`);
  }
}

実際に使ってみましょう🖐️

const smsSender = new SmsSender();
const emailSender = new EmailSender();

const textSms = new TextMessage(smsSender);
const textEmail = new TextMessage(emailSender);
const richSms = new RichMessage(smsSender);
const richEmail = new RichMessage(emailSender);

textSms.send("こんにちは!");    // 【SMSで送信】テキストメッセージ送信: こんにちは!
textEmail.send("こんにちは!");  // 【Eメールで送信】テキストメッセージ送信: こんにちは!
richSms.send("こんにちは!");    // 【SMSで送信】リッチメッセージ送信: ***こんにちは!***
richEmail.send("こんにちは!");  // 【Eメールで送信】リッチメッセージ送信: ***こんにちは!***

これで、Bridge Patternを使ったメッセージ送信アプリができました!

機能実装が独立しており拡張しやすいです。例えば、他のプラットフォーム(Slackなど)の追加が簡単です👍

クラス図

サンプルコードのクラス図:Mermaid Live Editorで作成

Bridge Patternの使い道

Bridge Patternは、機能の追加や実装の変更が予想されるシステムで特に効果を発揮します。

それぞれの機能と実装が独立しているため、拡張性が高く、変更に強い設計が可能です。

組み合わせられるデザインパターン

例えば、Adapter Patternと組み合わせることで、異なるインターフェースを持つクラス同士を繋げることができます。

https://chan-naru.hatenablog.com/entry/2023/03/28/165808chan-naru.hatenablog.com

また、Factory Method Patternと組み合わせることで、実装クラスのインスタンス化を柔軟に行うことができます。

chan-naru.hatenablog.com

まとめ

今回のサンプルでは、メッセージ送信アプリを例に、異なるプラットフォームで送信できるようにBridge Patternを適用しました✉️

Bridge Patternを使うことで、機能実装が独立し、拡張性が高く変更に強い設計が可能となります👍

参考文献

www.oreilly.com

en.wikipedia.org