これには、アダプタパターンが必要です。特定のカートインターフェイスを汎用インターフェイスに適合させます。
簡単な例:
/* existing cart implementation */
class CartFromVendorX
{
public function addProduct( CartXProduct $product ) {}
}
/* existing cart implementation */
class CartFromVendorY
{
public function pushProduct( CartYProduct $product ) {}
}
/* generic cart interface */
interface CartAdapterInterface
{
public function addItem( $item );
}
class CartAdapterVendorX
implements CartAdapterInterface
{
protected $adaptee;
public function __construct( CartFromVendorX $adaptee )
{
$this->adaptee = $adaptee;
}
public function addItem( $item )
{
/* transfrom generic $item to CartXProduct, for instance */
$this->adaptee->addProduct( $product );
}
}
class CartAdapterVendorY
implements CartAdapterInterface
{
protected $adaptee;
public function __construct( CartFromVendorY $adaptee )
{
$this->adaptee = $adaptee;
}
public function addItem( $item )
{
/* transfrom generic $item to CartYProduct, for instance */
$this->adaptee->pushProduct( $product );
}
}
次に、一般的なカートを消費するクライアント:
class CartClient
{
protected $cart;
public function __construct( CartAdapterInterface $cart )
{
$this->cart = $cart;
}
/* rest of implementation that acts on CartAdapterInterface instance */
}
使用法:
$cartAdapter = new CartAdapterVendorX( new CartFromVendorX() );
$client = new CartClient( $cartAdapter );
PS:元の実装をコンストラクターに渡すように、必ずしもアダプターを実装する必要はありません。このようなものも同様に機能する可能性があります。
class CartAdapterVendorX
implements CartAdapterInterface
{
protected $adaptee;
public function __construct()
{
$this->adaptee = new CartFromVendorX();
}
public function addItem( $item )
{
/* perhaps transfrom generic $item first */
$this->adaptee->addProduct( $item );
}
}
次に、その使用法は次のように単純化されます。
$cartAdapter = new CartAdapterVendorX();
$client = new CartClient( $cartAdapter );
実際の実装の詳細はさまざまですが、これで一般的な考え方がわかります。たとえば、一部またはすべての元のカートに対して、ファサードパターンを実装する可能性が高くなります。これは、1つの元の実装に対する複数のメソッド呼び出しをアダプタインターフェイスの単一のメソッドにラップする場合があるためです。