本記事に掲載したサンプルコードは、https://github.com/ryo-utsunomiya/design_patternでも公開中です。
Adapterパターンとは
Adapterパターンとは、2つのオブジェクトの間にギャップが有る時に、そのギャップを埋めるオブジェクトを用意することです。
継承によるAdapter
例えば、以下のクラスが既存のクラスとして存在しているとします。
<?php
namespace my;
class Banner
{
/**
* @var string
*/
private $string;
/**
* @param $string
*/
public function __construct($string)
{
$this->string = (string)$string;
}
public function showWithParen()
{
printf("(%s)n", $this->string);
}
public function showWithAster()
{
printf("*%s*n", $this->string);
}
}
このクラスは、与えられた文字列を()または**でくくって表示するメソッドを持っています。
ここで、「printWeak()」と「printStrong()」というメソッドを定義したいとします(ここでは、なぜこのメソッドの実装が必要なのかは問題にしません)。
実装方法の一例として、以下のインタフェースを定義します。
<?php
namespace my;
interface IPrint
{
public function printWeak();
public function printStrong();
}
これを満たしつつ、既存のクラスを再利用すると、以下のようなAdapterが実装できます。
<?php
namespace my;
class PrintBanner extends Banner implements IPrint
{
public function printWeak()
{
$this->showWithParen();
}
public function printStrong()
{
$this->showWithAster();
}
}
これが、継承を使ったAdapterパターンです。既存のBannerのメソッドを利用しつつ、printWeak()とprintStrong()を実装しています。
委譲によるAdapter
Adapterパターンは委譲を使っても実装できます。委譲を使う場合、インタフェースではなく、抽象クラスを使うことになります。
<?php
namespace my;
abstract class AbstractPrint
{
abstract protected function printWeak();
abstract protected function printStrong();
}
これを継承したクラスで、printWeak()とprintStrong()を実装します。
<?php
namespace my;
class PrintBanner extends AbstractPrint
{
/**
* @var Banner
*/
private $banner;
/**
* @param string $string
*/
public function __construct($string)
{
$this->banner = new Banner((string)$string);
}
public function printWeak()
{
$this->banner->showWithParen();
}
public function printStrong()
{
$this->banner->showWithAster();
}
}
継承と委譲のどちらがより優れているということはありません。利用したいオブジェクトや、完成品の形などから、適切な方法を選ぶことになります。