Nao000のぶろぐ

蝶を追っている少年になりたい

【デザインパターン】PHPを使ったアダプターパターンの例

【デザインパターン】PHPを使ってアダプターパターンの例

アダプターパターンは何が出来る?

ある物を異なる物として扱うことが出来ます。この記事ではドブネズミを猫として扱います。

概要

猫インターフェースを実装したオブジェクトは i_am_cat() というメソッドを実行できます。この i_am_cat() をネズミが実行するためにアダプターを使います。

この記事では i_am_cat() が実行出来るということは猫として扱います。

コード

Cat.php

まずは猫インターフェースを定義します。この猫インターフェースを実装したクラスは猫として扱います。

    <?php

    interface Cat {
        public function i_am_cat();
    }

MikeCat.php

三毛猫クラスです。三毛猫クラスは先程の猫インターフェースを実装しています。

    <?php

    require('Cat.php');
    /**
     * 三毛猫
     */
    class MikeCat implements Cat
    {
        public function i_am_cat() {

            echo '私は三毛猫です'.PHP_EOL.PHP_EOL;
        }
    }

Rat.php

ネズミインターフェースです。このネズミインターフェースを実装したクラスはネズミとして扱います。

    <?php

    interface Rat {
        public function i_am_rat();
    }

DobuRat.php

今回の主役であるドブネズミです。このドブネズミは先程のネズミインターフェースを実装したクラスです。

このオブジェクトが後に猫に化けます。

    <?php

    require('Rat.php');
    /**
     * ドブネズミ
     */
    class DobuRat implements Rat
    {
        public function i_am_rat() {

            echo 'ネズミです。ハハ'.PHP_EOL.PHP_EOL;
        }
    }

RatAdapter.php

今回の主役専用武器であるネズミアダプターです。このネズミアダプターは猫の振りをする強力な武器です。クラス名は悩みました。猫の振りをするので、猫アダプターかなとも思いますが、ネズミが使用するのでネズミアダプターとしました。

    <?php

    /**
     * ネズミが猫の振りをするアダプター
     */
    class RatAdapter implements Cat
    {
        private $rat;

        public function __construct($rat) {

            $this->rat = $rat;
        }

        public function i_am_cat() {

            $this->rat->i_am_rat();
        }
    }

Main.php

プログラムを実行するファイルです。 testCat 関数で猫とそれ以外を区別します。実行結果を続いて示します。

    <?php

    require('MikeCat.php');
    require('DobuRat.php');
    require('RatAdapter.php');

    $mikeCat = new mikeCat();
    $dobuRat = new dobuRat();
    // 三毛猫なので i_am_cat() が実行可能
    testCat($mikeCat);

    // ドブネズミはドブネズミなので i_am_cat() は実行不可
    testCat($dobuRat);

    // ドブネズミでも i_am_cat() を実行できるようにアダプターを使う
    $fakeCat = new ratAdapter($dobuRat);
    testCat($fakeCat);

    function testCat($animalObject) {

        // $animalObject に i_am_cat() が定義されていれば実行する
        if (method_exists($animalObject, 'i_am_cat')) {

            echo '【こちらの方は猫です】'.PHP_EOL;
            $animalObject->i_am_cat();
            return;
        }

        echo '【この動物は猫ではありません】'.PHP_EOL.PHP_EOL;
        return;
    }

実行結果

    PS D:studydesignpatternadptercat> php .main.php
    【こちらの方は猫です】
    私は三毛猫です

    【この動物は猫ではありません】

    【こちらの方は猫です】
    ネズミです。ハハ

    PS D:studydesignpatternadptercat>

上から順に、1回目は猫、2回目はドブネズミ、3回目はドブネズミ の順で実行しています。2回目のドブネズミはアダプターを通していませんので、 【この動物は猫ではありません】 として出力されます。

3回目のドブネズミはアダプターを通しているため猫として扱います。i_am_cat() が実行できているのが確認できます。

終わり

以上です。このパターンを使うときはプロジェクトが既にレガシーコードになりつつある状況な気がします。フレームワークのコアソースで扱われているかもですが、プロジェクトで使うときは慎重になったほうがいい気がします。