我使用什么 OOP 模式来提供默认值而不违反 Liskov 替换原则


What OOP pattern do I use to provide defaults without violating the Liskov substitution principle

我有一个类来控制我在几个项目中使用的外部 API(简化示例):

class PaymentModule
{
  public function doPayment($customer_name, $currency, $language)
  {
    curl_setopt(POSTFIELDS, array($customer_name, $currence, $language));
    curl_exec();
  }
}

现在在一个特定的项目中,我想"包装"它,并为许多我在这里不使用的参数提供合理的默认值。

所以我想,我将extend这个类,让我的 IDE 覆盖所有方法,然后删除我不使用的参数,如下所示:

class MyPaymentModule extends PaymentModule
{
  public function doPayment($customer_name)
  {
    $language = get_current_language();
    parent::doPayment($customer_name, 'EUR', $language);
  }
}

正如我现在了解到的(感谢 PHP 严格的标准),这违反了 Liskov 替换原则,即在 OOP 中,通常MyPaymentModule应具有与PaymentModule相同的接口,这反过来意味着MyPaymentModule::doPayment()应具有与PaymentModule::doPayment()相同的参数。

我认为您想要创建一个为另一个类提供合理默认值的类并不少见,那么这里有什么常见的模式可以使用吗?当然,我可以选择两个完全独立的类,但我更喜欢一个仍然暗示两个类之间关系的解决方案......毕竟,它们将始终具有相同的方法,只是具有较少参数的方法。

这在

你当前的类设计中是不可能的。我建议创建一个处理货币和语言的新类PaymentOptions。使用新方法setPayment选项或作为doPayment的可选参数传递选项。

这样的东西应该有效

class PaymentModule {
    /**
     * @var PaymentOptions
     */
    private $paymentOptions = null;
    function doPayment($customer_name, PaymentOptions $options = null) {
        if ($options == null) {
            $options = $this->paymentOptions;
        }
        if ($options == null) {
            throw new Exception('...');
        }
        //...
    }
    /**
     * @return PaymentOptions
     */
    public function getPaymentOptions()
    {
        return $this->paymentOptions;
    }
    /**
     * @param PaymentOptions $paymentOptions
     */
    public function setPaymentOptions($paymentOptions)
    {
        $this->paymentOptions = $paymentOptions;
    }
}
class MyPaymentModule extends PaymentModule {
    function doPayment($customer_name, PaymentOptions $options = null)
    {
        //...
    }
}
class PaymentOptions {
    private $currency;
    private $language;
    /**
     * @return mixed
     */
    public function getCurrency()
    {
        return $this->currency;
    }
    /**
     * @param mixed $currency
     */
    public function setCurrency($currency)
    {
        $this->currency = $currency;
    }
    /**
     * @return mixed
     */
    public function getLanguage()
    {
        return $this->language;
    }
    /**
     * @param mixed $language
     */
    public function setLanguage($language)
    {
        $this->language = $language;
    }
}