【问题标题】:PHP applying code from multiple classes that implement the same interfacePHP 应用来自多个实现相同接口的类的代码
【发布时间】:2019-03-29 21:45:00
【问题描述】:

我目前正在实施一个项目,并且对实现相同接口的多个类有疑问。

所以,现在我有多种折扣类型可以应用于订单。因此,我创建了一个包含 check() 方法的 DiscountInterface,用于检查折扣是否适用以及应用折扣的 apply() 方法。

到目前为止,一切都很好。然后我在一个实现 DiscountInterface 的类中实现了第一个折扣类型,并具有检查和应用这个特定折扣的逻辑。

在我的控制器中,我注入了 DiscountInterface。收到订单后,我同时调用 check() 和 apply() 方法,一切都运行良好。

我的问题如下。我实施第二种折扣。在我的实现之后,我将不得不创建一个实现 DiscountInterface 的新类。但是当需要在控制器上调用它时应该如何完成。因为我要上不同的课,用同样的方法。

如果我有一个类实现这些方法,则以下代码有效,但如果我有两个类实现它们会发生什么?

public function discount(
    Request $request, 
    DiscountInterface $discount, 
    CustomerRepository $customer, 
    ProductRepository $product, 
    ValidatorInterface $validator,
    OrderServiceInterface $orderService
)
{
    $data = json_decode($request->getContent(), true);
    $order = $orderService->convertDataToOrder($data, $customer, $product, $validator);

    if($discount->check($order, $customer)){
        $order = $discount->apply($order);
    }

【问题讨论】:

  • 代码将继续工作,它将采用任何满足“DiscountInterface”的类,因此即使您有 2 或 300 个类,您也可以将它们放入该方法中,因为它们完全可互换。
  • 您的控制器在哪里供我们查看?
  • 您是否需要检查所有折扣类型并找出适用的折扣类型?
  • 是的,我需要检查所有的折扣类型。

标签: php symfony oop interface


【解决方案1】:

如果您需要检查所有折扣类型,而不是传递实现类,为什么不传递DiscountFactory 呢?

<?php

use My\Discount\CrapDiscount;
use My\Discount\AwesomeDiscount;

class DiscountFactory
{
    /** @var DiscountInterface[] */
    private $discounts;

    public function __construct()
    {
        $this->discounts = [
            new CrapDiscount(),
            new AwesomeDiscount(),
        ];
    }

    public function getDiscounts(): array
    {
        return $this->discounts;
    }
}

那么您的代码可能如下所示:

public function discount(
    Request $request, 
    DiscountFactory $discountFactory, 
    CustomerRepository $customer, 
    ProductRepository $product, 
    ValidatorInterface $validator,
    OrderServiceInterface $orderService
)
{
    $data = json_decode($request->getContent(), true);
    $order = $orderService->convertDataToOrder($data, $customer, $product, $validator);

    foreach ($discountFactory->getDiscounts() as $discount) {
        if($discount->check($order, $customer)){
            $order = $discount->apply($order);
        }
    }
    // etc

【讨论】:

  • 听起来像个计划!感谢您的想法!
  • @CláudioRibeiro 请注意,您可能需要添加检查以验证折扣顺序;折现一个金额然后减去一个百分比与反过来做是不一样的。
  • 干杯!如果它有效,你能把它标记为正确吗? :-D
  • @Claudio 我把它移到了构造函数中
猜你喜欢
  • 2014-03-05
  • 2014-10-25
  • 2021-10-18
  • 2018-05-19
  • 2022-08-18
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多