Facadeパターン

外部に使いやすい機能を提供しよう

今までメーカーからExcelファイルで新規商品のデータを受け取り、商品登録用のシステムに登録するという運用になっているところ、 メーカーにPHPのプログラムを提供することで、メーカーから新商品のデータを受け取れるようにしようと思いました。

SDKを1から作るのも面倒なので、現在稼働中の商品登録用のシステムに「最小限の改修」をした状態で提供します。 どうしたら良いでしょうか?

Facadeパターン

Facadeパターンとは、複雑な処理を隠蔽しシンプルな窓口を作るパターンです。 たとえば既存の商品登録機能が下記のような場合を考えましょう。

/**
 * 商品情報.
 */
class Product
{
  private string $maker;
  private string $productCode;
  private string $productName;
  private int $price;
  public function getPrice(): int
  {
    return $this->price;
  }

  public function setPrice(int $price)
  {
    $this->price = $price;
  }

  public function getProductName(): string
  {
    return $this->productName;
  }

  public function setProductName(string $productName): self
  {
    $this->productName = $productName;

    return $this;
  }

  public function getProductCode(): string
  {
    return $this->productCode;
  }

  public function setProductCode(string $productCode): self
  {
    $this->productCode = $productCode;

    return $this;
  }

  public function getMaker(): string
  {
    return $this->maker;
  }

  public function setMaker(string $maker): self
  {
    $this->maker = $maker;

    return $this;
  }
}

/**
 * 商品登録
 */
class ProductRegister
{
  public function register(Product $product): void
  {
    // 登録処理.
    echo "下記商品を登録します\n";
    echo $product->getMaker();
    echo "\n";
    echo $product->getProductCode();
    echo "\n";
    echo $product->getProductName();
    echo "\n";
    echo $product->getPrice();
    echo "\n";
    echo "上記商品を登録しました\n";
  }
}

$register = new ProductRegister();
$product = new Product();
$product->setMaker('CPUメーカーA');
$product->setProductCode('AAABBBCC');
$product->setProductName('はやいCPU');
$product->setPrice(30000);
$register->register($product);

メーカーが手軽に登録できるように、元のクラスとメソッドを修正せず、 メーカー名を設定する手間が無いようなクラスを作りましょう。

class CpuProductRegisterFacade
{
  public static function register(string $productCode, string $productName, int $price): void
  {
    $register = new ProductRegister();
    $product = new Product();
    // 提供先メーカーの名前を固定で入力することで、引数の数を減らす
    // 保守性を高めるためには直接文字列を設定するのではなく、
    // 設定ファイルやオブジェクト定数にすべき
    $product->setMaker('CPUメーカーA');
    $product->setProductCode($productCode);
    $product->setProductName($productName);
    $product->setPrice($price);
    $register->register($product);
  }
}

// 一行で処理ができ、引数も1つで済むようになった(
CpuProductRegisterFacade::register('AAABBBCC', 'はやいCPU', 30000);

Facadeを作ることで、3つの引数だけで登録する事ができました。 今回の例はあまりにシンプルすぎて効果が分かりづらいですが、 既存の処理が複雑であればあるほどFacadeパターンは有効に働くでしょう。