有时我们想使用一些类,但不幸的是,它们并不总是有我们需要的方法,或者它们随着时间的推移而改变,变得不兼容。在这种情况下,适配器模式可以帮助我们将不兼容的接口调整为兼容的接口,供我们的类使用。
例子
假设下面的TaxCalculator类不属于我们的团队,我们没有能力去改变它。我们所做的只是在我们的代码中使用它。
class TaxCalculator
{
private $amount;
private $rate;
public function setAmountAndRate($amount, $rate)
{
$this->amount = $amount;
$this->rate = $rate;
return $this;
}
public function calculate()
{
return $this->amount * $this->rate;
}
}
这就是我们如何使用它:
$taxCalculator = new TaxCalculator();
echo $taxCalculator->setAmountAndRate(100, 0.5)->calculate();
假设我们在很多地方使用了上面的代码,其他团队决定改变TaxCalculator类,使其看起来像下面的类:
class TaxCalculator
{
private $amount;
private $rate;
public function setAmount($amount)
{
$this->amount = $amount;
return $this;
}
public function getAmount()
{
return $this->amount;
}
public function setRate($rate)
{
$this->rate = $rate;
return $this;
}
public function getRate()
{
return $this->rate;
}
public function calculate()
{
return $this->amount * $this->rate;
}
}
正如你所看到的,我们下面的原始代码将被破坏,因为setAmountAndRate 方法已经被分割成两个不同的方法。
$taxCalculator = new TaxCalculator();
echo $taxCalculator->setAmountAndRate(100, 0.5)->calculate();
由于这些变化,我们现在必须使我们的原始代码看起来像下面的代码。
$taxCalculator = new TaxCalculator();
echo $taxCalculator->setAmount(100)->setRate(0.5)->calculate();
如果我们在应用程序的许多不同地方使用同一段代码,这将是一项艰巨的任务。你永远不知道,TaxCalculator类可能在将来再次被改变,我们最终也会重复自己。为了避免这种问题,我们可以在下面引入类。
interface AdapterInterface
{
public function calculate();
}
class TaxCalculatorAdapter implements AdapterInterface
{
public $taxCalculator;
public function __construct(TaxCalculator $taxCalculator)
{
$this->taxCalculator = $taxCalculator;
}
public function calculate()
{
return $this->taxCalculator->getAmount() * $this->taxCalculator->getRate();
}
}
$taxCalculator = new TaxCalculator();
$taxCalculator->setAmount(100)->setRate(0.5);
$taxCalculatorAdapter = new TaxCalculatorAdapter($taxCalculator);
echo $taxCalculatorAdapter->calculate();
如果TaxCalculator类再次改变,我们只需要改变TaxCalculatorAdapter本身一次,其他什么都不用做。