【PHPデザインパターン】16_Mediator~すべては相談役が知っている


引用記事

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

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

Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Mediator~すべては相談役が知っている

概要

  • 「mediator」とは「仲介者」「調停者」という意味。
  • 関連しあうクラス群のやり取りを1つのオブジェクトに集約させる。
  • 仲介者とクラスの関係を一対多にし、仲介者のクラスだけを知っていれば、他のクラスを知らなくてもお互いにやり取りできるようにする。
  • クラス同士のやり取りを一極集中させ、他のクラスとの結びつきをゆるくして互いに独立性を持たせる。

構成要素

Mediatorクラス

  • 仲介者のクラス。
  • Colleagueクラスからの通知を受け取るメソッドを定義する。

ConcreteMediatorクラス

  • Mediatorクラスのサブクラス。

Colleagueクラス

  • 「colleague」は「同僚」「仲間」という意味。
  • Mediatorクラスに通知を行うクラス。
  • Mediatorクラスからの通知を受け取るメソッドを定義する場合もある。

ConcreteColleagueクラス

  • Colleagueクラスのサブクラス。
  • 内部にMediatorオブジェクトを保持し、このMediatorオブジェクトを通じて他のConcreteColleagueクラスとやり取りを行う。

実演

処理の流れ

  • Userクラス同士のやり取りをChatroomクラスが仲介する。
  • Userクラス同士でメッセージの送受信ができる。その時、Chatroomクラスはメッセージのルーティングを行う。
  • UserクラスはChatroom型オブジェクトを保持している。このオブジェクトを通じて他のUser型オブジェクトとやり取りを行う。

ファイル構造

MyMediator
  ├── Chatroom.php
  ├── User.php
  └── my_client.php

ソースコード

Mediatorクラス

兼ConcreteMediatorクラス。

Chatroom.php

Chatroom.php
<?php
namespace DoYouPhp\PhpDesignPattern\Mediator\MyMediator;

use DoYouPhp\PhpDesignPattern\Mediator\MyMediator\User;

/**
 * MediatorクラスとConcreteMediatorクラスに相当する
 */
class Chatroom
{
    // User型インスタンスを配列として保持する
    private $users = array();

    // ログイン時の処理
    public function login(User $user)
    {
        // UserクラスにChatroom型オブジェクトをセットする
        $user->setChatroom($this);
        // ログイン時、$usersに存在しないユーザーであれば$usersに追加する
        // キーはユーザー名とする
        if (!array_key_exists($user->getName(), $this->users)) {
            $this->users[$user->getName()] = $user;
            // 入室のメッセージを出力する
            echo $user->getName().'さんが入室しました'.'<br>'."\n";
        }
    }

    // 相手にメッセージを送る
    public function sendMessage($from, $to, $message)
    {
        // 相手が入室している場合はメッセージを受け取る
        // メッセージはUserクラスのメソッドから出力する
        if (array_key_exists($to, $this->users)) {
            $this->users[$to]->receiveMessage($from, $message);
        } else {
            // 相手が入室していない場合は、メッセージを出力する
            echo $to.'さんは入室していないようです'.'<br>'."\n";
        }
    }
}

Colleagueクラス

兼ConcreteColleagueクラス。

User.php

User.php
<?php
namespace DoYouPhp\PhpDesignPattern\Mediator\MyMediator;

use DoYouPhp\PhpDesignPattern\Mediator\MyMediator\Chatroom;

/**
 * ColleagueクラスとConcreteColleagueクラスに相当する
 */
class User
{
    // Chatroom型インスタンスを保持する
    private $chatroom;
    // ユーザー名
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

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

    // ログイン時に実行される
    // チャットルームをセットする
    public function setChatroom(Chatroom $value)
    {
        $this->chatroom = $value;
    }

    public function getChatroom()
    {
        return $this->chatroom;
    }

    // メッセージを送る
    // メッセージのルーティングはChatroomクラスで行う
    public function sendMessage($to, $message)
    {
        $this->chatroom->sendMessage($this->name, $to, $message);
    }

    // ルーティングの結果、受け取ったメッセージを表示する
    // Chatroomクラスから差出人の名前とメッセージを受け取る
    public function receiveMessage($from, $message)
    {
        echo $from.'さんから'.$this->getName().'さんへ:'.$message.'<br>'."\n";
    }
}

Clientクラス

my_client.php

my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Mediator\MyMediator;

require dirname(dirname(__DIR__)).'/vendor/autoload.php';

use DoYouPhp\PhpDesignPattern\Mediator\MyMediator\Chatroom;
use DoYouPhp\PhpDesignPattern\Mediator\MyMediator\User;

    // Chatroom型インスタンスを生成する
    $chatroom = new Chatroom();

    // User型インスタンスを生成する
    $sasaki = new User('佐々木');
    $suzuki = new User('鈴木');
    $yoshida = new User('吉田');

    // Chatroomクラスからログインのメソッドを実行する
    $chatroom->login($sasaki);
    $chatroom->login($suzuki);
    $chatroom->login($yoshida);

    // メッセージを送信する
    $sasaki->sendMessage('鈴木', 'こんにちは!');
    $suzuki->sendMessage('吉田', 'お久しぶりです!');
    $yoshida->sendMessage('萩原', 'お世話になっています!');