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

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

Adapterとは**「適合する」**という意味で、Wrapperパターンと呼ばれることもある。
「すでに提供されているもの」を「利用できるもの」にするためのデザインパターン

## Adapterパターンを構成する内容の役割
・Target:必要なメソッドを持っているインターフェース。メソッドの実装方法は定めず抽象メソッドを定義している。
・Adapter:変換するための機能を持つクラス
・Adaptee:利用したいメソッドを持っているクラス


## どういう時に使用可能なのか
・関連性のないクラス同士を既存のクラスを変えずに関連付けする場合
・既存のクラスをある新しいインターフェイスを通じて再利用したい場合
・既存のクラス・インターフェイスをアプリケーション固有なものに(使いやすく)したい場合
などの際に有効なパターンである

[参考サイト]
https://ja.wikipedia.org/wiki/Adapter_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
https://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976
https://www.programming-fun.net/article/article_77.html

# Adapterパターンを用いるメリット

・既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。
・既存のクラスをもう一度動作テストする必要がなくなる
・Adapterパターンによってバグが発生しても、既存のクラスには変更を加えていないためバグがないことが保証される

# サンプルコード

## 仕様

消費税を計算する。ゲームとかでアイテムやガチャを販売する際の値段に税率を反映させたい。
詳細は以下。
・原価管理のクラス(adaptee):Cost
・消費税計算後(adapter):CostIncludingComsumptionTax
・消費税計算後のクラスのインターフェース(target):CostIncludingComsumptionTaxInterface

今回は同様な仕様で、継承を利用したもの、委譲を利用したものを記載する。

## 継承を利用したパターン

```php:CostIncludingComsumptionTaxInterface
interface CostIncludingComsumptionTaxInterface {
    public function getItemCostIncludingComsumptionTax();

    public function getGachaCostIncludingComsumptionTax();
}
```

```php:Cost.class.php
class Cost {
    private $itemCost = 100;
    private $gachaCost = 500;

    // アイテムの費用取得
    public function getItemCost()
    {
        return $this->itemCost;
    }

    // ガチャの費用取得
    public function getGachaCost()
    {
        return $this->gachaCost;
    }
}
```

```php:CostIncludingComsumptionTax.class.php
class CostIncludingComsumptionTax extends Cost implements CostIncludingComsumptionTaxInterface {

    private $taxRate = 10; // 税率(%)

    // 消費税を適用したアイテムの費用を返します。
    public function getItemCostIncludingComsumptionTax()
    {
        return $this->getItemCost() * (1 + ($this->taxRate / 100));
    }

    // 消費税を適用したガチャの費用を返します
    public function getGachaCostIncludingComsumptionTax()
    {
        return $this->getGachaCost() * (1 + ($this->taxRate / 100));
    }
}
```

呼び出し

```php
$cost = new CostIncludingComsumptionTax();

echo $cost->getItemCostIncludingComsumptionTax() . PHP_EOL;
echo $cost->getGachaCostIncludingComsumptionTax() . PHP_EOL;

/*
110
550
*/
```

## 委譲を利用したパターン

adaptee、targetについては継承を利用したパターンと同様

```php:CostIncludingComsumptionTax.class.php
class CostIncludingComsumptionTax implements CostIncludingComsumptionTaxInterface {

    private $taxRate = 10; // 税率(%)
    private $costData = null;

    public function __construct()
    {
        if (! $this->costData instanceof Cost) {
            $this->costData = new Cost();
        }
    }

    // 消費税を適用したアイテムの費用を返します。
    public function getItemCostIncludingComsumptionTax()
    {
        return $this->costData->getItemCost() * (1 + ($this->taxRate / 100));
    }

    // 消費税を適用したガチャの費用を返します
    public function getGachaCostIncludingComsumptionTax()
    {
        return $this->costData->getGachaCost() * (1 + ($this->taxRate / 100));
    }
}```

呼び出し

```php
$cost = new CostIncludingComsumptionTax();

echo $cost->getItemCostIncludingComsumptionTax() . PHP_EOL;
echo $cost->getGachaCostIncludingComsumptionTax() . PHP_EOL;

/*
110
550
*/
```

# まとめ

・関連性のないクラスの必要な処理を一つのクラスに**既存クラスに修正を加えることなく**まとめることができる部分が大きなメリットであると感じた。
・継承より委譲で使用したほうがもろもろ融通が効きそうな気がした(直感的にではあるが)