Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【PHPデザインパターン】05_Façade~シンプルな唯一の窓口

More than 1 year has passed since last update.

引用記事

この記事を書くきっかけになったブログです。

記事内の解説やソースコードは、こちらのブログと著者の公開リポジトリを参考にしています。

Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Façade~シンプルな唯一の窓口

概要

  • サブシステム内に存在する複数のインターフェースに1つの統一インターフェースを与える。
  • 複雑に連携しあうクラスやオブジェクトを容易に扱うための窓口(API)を提供する。
  • クライアントからはサブシステムの入り口しか見えなくなり、同時にサブシステムとの結びつきがゆるくなる。その結果、互いの独立性が高くなる。
  • 非常に大きな「カプセル化」を行なっている。
  • 「façade」は「ファサード」と読む。(フランス語で「正面窓口」という意味)

構成要素

Façadeクラス

  • サブシステムで提供される統一APIを持つクラス。
  • サブシステム内のクラス同士の関係を知っている。

サブシステム内のクラス群

  • サブシステムを構成するクラス群。
  • Façadeクラスの存在は知らない。

Clientクラス

  • サブシステムを利用するクラス。
  • Façadeクラスを通じてサブシステムにアクセスする。
  • サブシステム内のクラス同士の関係は見えない。

実演

著者のソースコードと比べると、かなり簡単な内容になっています。

処理の流れ

  • 注文データを配列形式で受け取り、メッセージを出力する。
  • my_client.phpはClientクラスに該当する。
  • ManagerクラスはFaçadeクラスに該当する。
  • OrderクラスCalcMessageクラスをサブシステムとする。
  • Orderクラスで注文情報をセットする。
  • CalcMessageクラスで合計金額を計算し、注文内容のメッセージを出力する。

ファイル構造

MyFacade
   ├── CalcMessage.php
   ├── Manager.php
   ├── Order.php
   └── my_client.php

ソースコード

my_client.php

my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Facade\MyFacade;
require dirname(dirname(__DIR__)).'/vendor/autoload.php';

use DoYouPhp\PhpDesignPattern\Facade\MyFacade\Manager;
use DoYouPhp\PhpDesignPattern\Facade\MyFacade\Order;
use DoYouPhp\PhpDesignPattern\Facade\MyFacade\CalcMessage;

// 配列型の注文データ
$order_data = array(1, 'りんご', 100, 3);

// Managerクラスを窓口にして必要な処理を行う
Manager::order($order_data);

Manager.php

Manager.php
<?php
namespace DoYouPhp\PhpDesignPattern\Facade\MyFacade;

use DoYouPhp\PhpDesignPattern\Facade\MyFacade\Order;
use DoYouPhp\PhpDesignPattern\Facade\MyFacade\CalcMessage;

class Manager
{
    // 注文データを元にサブシステムで必要な処理を行わせる
    public function order($order_data)
    {
        // Orderクラスのインスタンスを生成し、必要なプロパティがセットされる
        // Singletonパターンを利用してオブジェクトの複製を防いでいる
        $order = Order::getInstance($order_data);

        // CalcMessageクラスのインスタンスを生成する
        // 注文内容を計算し、メッセージを返す
        $calc_message = new CalcMessage($order);
        $calc_message->createMessage();

        // cloneを試して複製できないことを確認する
        try {
            $order_clone = clone $order;
        } catch (\RuntimeException $e) {
            echo $e->getMessage().'<br>'."\n";
        }
    }
}

Order.php

Order.php
<?php
namespace DoYouPhp\PhpDesignPattern\Facade\MyFacade;

// 注文内容をプロパティとして保有する
class Order
{
    private $id;
    private $name;
    private $price;
    private $amount;
    // $instanceはオブジェクト型のプロパティ
    private static $instance;

    // 配列型の注文データからプロパティをセットする
    private function __construct($order_data)
    {
        list($this->id, $this->name, $this->price, $this->amount) = $order_data;
    }

    // 他クラスからオブジェクトを生成する場合は、こちらのメソッドを利用する
    // staticメソッドなので、オブジェクト未作成の状態から呼び出せる
    // オブジェクトが存在しない場合のみ、新規にオブジェクトを生成する
    public function getInstance($order_data)
    {
        if (!isset(self::$instance)){
            self::$instance = new Order($order_data);
        }

        return self::$instance;
    }

    // セットしたプロパティを返す
    public function getId()
    {
      return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getPrice()
    {
        return $this->price;
    }

    public function getAmount()
    {
        return $this->amount;
    }

    // Singletonパターンを利用してオブジェクトの複製を防ぐ
    final public function __clone()
    {
        throw new \RuntimeException(get_class($this).'クラスのオブジェクトは複製できません');
    }
  }

CalcMessage.php

CalcMessage.php
<?php
namespace DoYouPhp\PhpDesignPattern\Facade\MyFacade;

// 注文合計額を計算しメッセージを返す
class CalcMessage
{
    // $orderはオブジェクト型のプロパティ
    private $order;
    private $order_sum;

    // Orderオブジェクトを引数にして必要なプロパティをセットする
    public function __construct(Order $order)
    {
        $this->order = $order;

        // 価格*個数の値をプロパティにセットする
        $order_price = $this->order->getPrice();
        $order_amount = $this->order->getAmount();
        $this->order_sum = $order_price * $order_amount;
    }

    // 注文内容と計算結果のメッセージを返す
    public function createMessage()
    {
        echo '注文ID'.$this->order->getId().'で'.$this->order->getName().'を注文しました!'.'<br>'."\n";
        echo '注文合計は'.$this->order_sum.'円です!'.'<br>'."\n";
    }
}
yukibe
2018年8月よりWebエンジニア。主にPHP。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away