※学習用メモ デザインパターン:Proxy編[PHP]

# Proxyパターンとはどういうものか

Proxyとは**代理人**という意味です。

>Proxy（プロキシ、代理人）とは、大まかに言えば、別の物のインタフェースとして機能するクラスである。その「別の物」とは何でもよく、ネットワーク接続だったり、メモリ上の大きなオブジェクトだったり、複製がコスト高あるいは不可能な何らかのリソースなどである。(wikipediaより)

要約すると、処理全体に大きなリソースを要する場合、その一部の処理をProxy(代理人)がこなす、というものです。

## 登場するクラス
・**Subject**:ProxyとRealSubjectを同一視するためのインターフェース
・**Proxy**:RealSubjectの処理を一部代替するクラス。
　自身で処理できないものはRealSubjectに任せる。Proxyでは、本当にRealSubjectが必要となった際のみRealSubjectを生成する。
・**RealSubject**:代理人であるProxyが処理できない際に処理を行うReal(本人)のクラス

# Proxyパターンのメリット

・メリット
多くのリソースが必要となる処理が必要ない場合、代理人のクラスその部分以外の処理を任せることで処理を省力化できる

[参考]
https://ja.wikipedia.org/wiki/Proxy_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
https://qiita.com/i-tanaka730/items/47efbab5eccc2d36759f
https://tic40.hatenablog.com/entry/2017/06/21/080000
https://www.ritolab.com/entry/142

# サンプルコード

## 仕様

・キャラクターの情報を表示します。
・キャラクターの画像の読み込みに時間を要するため、画像の表示の必要が無い場合は処理をProxy(代理人)のクラスにて行います。

ProxyとRealSubjectのインターフェース(Subject)

```CharacterInfoInterface.php
/**
 * Subjectインターフェース
 */
interface CharacterInfoInterface
{
    public function getCharacterInfo();
    public function displayImage();
}
```

キャラクターのクラス

```Character.class.php
/**
 * キャラクターのクラス
 */
class Character
{
    private $name = "";
    private $img = "";
    private $profession = "";

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

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

    public function getImg()
    {
        return $this->img;
    }

    public function getProfession()
    {
        return $this->profession;
    }
}
```

代理人として処理を行うクラス(Proxy)
ここでは画像表示以外の処理を代理で行います。
画像表示についてはRealSubjectに任せています。

```CharacterInfoProxy.class.php
/**
 * キャラクター情報の代理人クラス
 */
class CharacterInfoProxy implements CharacterInfoInterface
{
    private $character = "";

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

    public function getCharacterInfo()
    {
        return "名前:" . $this->character->getName() . "\n" .
        "職業:" . $this->character->getProfession() . "\n";
    }

    public function displayImage()
    {
        $real = new RealCharacterInfo($this->character);
        return $real->displayImage();
    }
}
```

本人クラス(RealSubject)
ここでは画像表示処理に必要なリソースが大きい仕様のため、sleepメソッドを用いて疑似的に重くしています。
また、動作の流れが分かるよう都度出力を行っています。

```RealCharacterInfo.class.php
/**
 * キャラクター情報の本人クラス
 */
class RealCharacterInfo implements CharacterInfoInterface
{
    private $character = "";

    public function __construct($character)
    {
        $this->character = $character;
        echo "====RealCharacterInfoを生成しました。====\n";
    }

    public function getCharacterInfo()
    {
        return "名前:" . $this->character->getName() . "\n" .
        "職業:" . $this->character->getProfession() . "\n";
    }

    public function displayImage()
    {
        echo "画像表示処理中...\n";
        for ($i = 0; $i < 2; $i++) {
            sleep(1);
            echo "*\n";
        }
        echo "完了\n";

        return $this->character->getImg();
    }
}
```

## 使ってみる

```php
$character = new Character("影虎", "/AAA/kagetora.png", "将軍");
$characterInfoProxy = new CharacterInfoProxy($character);

print_r($characterInfoProxy->getCharacterInfo());
print_r($characterInfoProxy->displayImage());

/*結果
名前:影虎
職業:将軍
====RealCharacterInfoを生成しました。====
画像表示処理中...
*
*
完了
/AAA/kagetora.png
*/
```

# まとめ

・Proxyパターンは、処理に大きなリソースを要する場合、その一部の処理をProxy(代理人)がこなすことで処理を省力化できます。
・このパターンは今までのパターンとはやや視点が異なり、処理のリソースなどに目を向けるものでありましたが、今まであまり処理のリソース等について考慮できていなかった為今後のプログラム作成・設計の際にも意識しておこうと感じました。