ちゃんなるぶろぐ

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

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

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

今回は、Adapter Patternを紹介します👍

概要

ひとことで言うと「互換性のないインターフェースを持つクラスをつなぐ」ためのデザインパターンです🖐️

既に提供されているものと今必要なもののギャップを埋めるデザインパターンとも表現できます。

Wrapper Pattern と呼ばれることもあるらしいです👀

プログラム設計

今回、異なるメッセージングサービスを統一的に扱えるシステムを例に、Adapter Patternを適用してみます🖐️

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

class SlackService {
  sendSlackMessage(message: string): void {
    console.log(`Slack message: ${message}`);
  }
}

class SlackMessageAdapter implements MessageSender {
  private slackService: SlackService;

  constructor(slackService: SlackService) {
    this.slackService = slackService;
  }

  sendMessage(message: string): void {
    this.slackService.sendSlackMessage(message);
  }
}

class NotificationSystem {
  private messageSender: MessageSender;

  constructor(messageSender: MessageSender) {
    this.messageSender = messageSender;
  }

  notify(message: string): void {
    this.messageSender.sendMessage(message);
  }
}

では、活用してみましょう。

const slackService = new SlackService();
const slackAdapter = new SlackMessageAdapter(slackService);
const notificationSystem = new NotificationSystem(slackAdapter);

notificationSystem.notify("Hello, Adapter Pattern!");

シンプルですね🤝

クラス図

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

  • クラス名: MessageSender(役割: ターゲットインターフェース)
  • クラス名: SlackService(役割: アダプティ)
  • クラス名: SlackMessageAdapter(役割: アダプター)
  • クラス名: NotificationSystem(役割: クライアント)

Adapter Patternの使い道

Adapter Patternは、システムの一部を別のシステムと連携させる必要がある場合や、異なるインターフェースを持つクラスを統一的に扱いたいときに適用されます。

このパターンは、既存のコードに影響を与えずに新しい機能を追加するためにも役立ちます。

サンプルコードの続き

では、Slack以外のシステムを追加してみましょう。

class DiscordService {
  sendDiscordMessage(message: string): void {
    console.log(`Discord message: ${message}`);
  }
}

class DiscordMessageAdapter implements MessageSender {
  private discordService: DiscordService;

  constructor(discordService: DiscordService) {
    this.discordService = discordService;
  }

  sendMessage(message: string): void {
    this.discordService.sendDiscordMessage(message);
  }
}

Discordのアダプタを追加したので、NotificationSystemでDiscordを使って通知を送ることができます。

const discordService = new DiscordService();
const discordAdapter = new DiscordMessageAdapter(discordService);
const notificationSystemWithDiscord = new NotificationSystem(discordAdapter);

notificationSystemWithDiscord.notify("Hello, Adapter Pattern with Discord!");

これで、SlackとDiscordの両方のメッセージングサービスを同じNotificationSystemを使って統一的に扱えるようになりました。

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

例えば下記のような組み合わせが考えられます。

  1. Facade Pattern: アダプタとファサードのパターンはよく似ているが、アダプタは異なるインターフェースを統合するのに対して、ファサードは複雑なシステムを簡素化したインターフェースを提供します。これらのパターンを組み合わせることで、より柔軟なクラス設計が可能になります。

chan-naru.hatenablog.com

  1. Bridge Pattern: Bridge Patternは、実装と抽象を分離して拡張しやすくするパターンです。Adapter Patternと組み合わせることで、異なるインターフェースを持つクラス間の連携を強化できます。

chan-naru.hatenablog.com

まとめ

Adapterパターンは、異なるインターフェースを持つクラスを統合する効果的なデザインパターンです。

システム間のスムーズな連携や新旧インターフェースの適合に役立ち、実際の開発で活用してみてください👍

参考文献

www.oreilly.com

en.wikipedia.org