💠

【デザインパターン】Facadeパターン

2023/03/08に公開約3,000字

Facadeパターンについて

Facadeはフランス語で建物の正面という意味がある。
Facadeパターンは、設計パターンの一つであり、複雑なシステムの内部構造を隠蔽し、シンプルなインターフェースを提供することによって、システムの利用を容易にする目的で使用されます。
Facadeパターンを使用することで、システムの利用者は、システム内部の複雑な処理や構造について知る必要がなくなります。代わりに、シンプルなインターフェースを通じて、必要な機能を利用することができます。

Facadeパターンの構成要素

Facadeパターンは、以下の要素から構成されています

  • Client: システムを利用するユーザー
  • Facade: システムのインターフェースを提供するクラス、実際の処理はシステム内部のクラス(SubSystemに委譲する)
  • Subsystem1, Subsystem2: システム内部の複雑な処理を担当するクラス

Facadeパターンを使用することで、Clientは、Facadeを通じて、Subsystem1やSubsystem2の機能を利用することができます。
Facadeは、Subsystem1やSubsystem2の内部処理を隠蔽し、シンプルなインターフェースを提供することによって、Clientの利用を容易にします。

Facadeパターンを用いない実装例

以下のような3つの機能が存在するとします。
これらは支払い処理をするさいのメソッド群で同時に利用されるケースが多いです。

class Product {
  getProduct(name: string) {
    console.log(`${name}を取得しました`);
  }
}

class Payment {
  makePayment(name: string) {
    console.log(`${name}の支払いが完了しました`);
  }
}

class Invoice {
  sendInvoice(name: string) {
    console.log(`${name}の請求書が送信されました`);
  }
}

これらを実行する場合は以下のようになりますね。

// 懇親会費の請求書を送信する
const product = new Product();
product.getProduct("懇親会費");

const payment = new Payment();
payment.makePayment("懇親会費");

const invoice = new Invoice();
invoice.sendInvoice("懇親会費");

それでは、別の支払い処理も作成してみましょう。

// 部費の請求書を送信する
const product = new Product();
product.getProduct("部費");

const payment = new Payment();
payment.makePayment("部費");

const invoice = new Invoice();
invoice.sendInvoice("部費");

まとめて使用する機能にも関わらず、別で呼び出してあげる必要が出てくるのでとても面倒ですね
では、Facadeパターンを用いて実装するとどうなるでしょうか

Facadeパターンを用いる例

FacadeとしてのOrderクラスを作成し、機能を包んであげました。
このように窓口を作り、そこから機能を提供することで個別にクラスの制御をしなくてもよくなりましたね。

class Product {
  getProduct(name: string) {
    console.log(`${name}を取得しました`);
  }
}

class Payment {
  makePayment(name: string) {
    console.log(`${name}の支払いが完了しました`);
  }
}

class Invoice {
  sendInvoice(name: string) {
    console.log(`${name}の請求書が送信されました`);
  }
}

class Order {
  static placeOrder(name: string) {
    console.log("start order");

    const product = new Product();
    product.getProduct(name);

    const payment = new Payment();
    payment.makePayment(name);

    const invoice = new Invoice();
    invoice.sendInvoice(name);

    console.log("order is completed");
  }
}

Order.placeOrder("懇親会費");
Order.placeOrder("部費")

それでは、Invoiceメソッドにい変更が入り、特定の個人に請求書を送信することになったとします。
その場合も簡潔に対応することができますね。

class Product {
  getProduct(name: string) {
    console.log(`${name}を取得しました`);
  }
}

class Payment {
  makePayment(name: string) {
    console.log(`${name}の支払いが完了しました`);
  }
}

class Invoice {
  sendInvoice(name: string, targetMember: string) {
    console.log(`${name}の請求書が${targetMember}に送信されました`);
  }
}

class Order {
  static placeOrder(name: string, targetMember: string) {
    console.log("start order");

    const product = new Product();
    product.getProduct(name);

    const payment = new Payment();
    payment.makePayment(name);

    const invoice = new Invoice();
    invoice.sendInvoice(name, targetMember);

    console.log("order is completed");
  }
}

Order.placeOrder("懇親会費", "会計部1");
Order.placeOrder("部費", "会計部2")

Discussion

ログインするとコメントできます