【问题标题】:What OOP pattern do I use to provide defaults without violating the Liskov substitution principle在不违反 Liskov 替换原则的情况下,我使用什么 OOP 模式来提供默认值
【发布时间】:2015-03-16 07:46:50
【问题描述】:

我有一个控制我在多个项目中使用的外部 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() 相同的参数。

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

【问题讨论】:

    标签: php oop


    【解决方案1】:

    这在您当前的班级设计中是不可能的。 我建议创建一个处理货币和语言的新类 PaymentOptions。 使用新方法 setPaymentOptions 或作为 doPayment 的可选参数将选项传递给 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      • 2021-11-17
      • 1970-01-01
      • 2017-07-04
      • 1970-01-01
      • 2015-01-21
      相关资源
      最近更新 更多