【问题标题】:Applying a design pattern for a certain behavior为特定行为应用设计模式
【发布时间】:2012-05-02 04:56:13
【问题描述】:

我想知道是否有人可以为此功能提供设计模式或更好的实现解决方案:

  public function refundAcceptedDisputes() {            
        $this->getRequestedEbayOrdersFromDB(); //get all disputes requested on ebay
        foreach ($this->orders as $order) { /* $order is a Doctrine Entity */
            try {
                if ($this->isDisputeAccepted($order)) {
                    $order->setStatus('accepted');
                    $order->refund(); //refunds the order on ebay and internally in my system
                    $this->insertRecordInOrderHistoryTable($order,'refunded');                        
                } else if ($this->isDisputeCancelled($order)) {
                    $order->setStatus('cancelled');
                    $this->insertRecordInOrderHistory($order,'cancelled');
                    $order->rollBackRefund(); //cancels the refund on ebay and internally in my system
                } else if ($this->isDisputeOlderThan7Days($order)) {
                    $order->closeDispute(); //closes the dispute on ebay
                    $this->insertRecordInOrderHistoryTable($order,'refunded');
                    $order->refund(); //refunds the order on ebay and internally in my system
                }
            } catch (Exception $e) {
                $order->setStatus('failed');
                $order->setErrorMessage($e->getMessage());
                $this->addLog();//log error
            }
            $order->setUpdatedAt(time());
            $order->save();
        }
    }

功能用途:

  • 我在 ebay 上卖游戏。
  • 如果客户希望取消他的订单并取回他的钱 (即退款)我必须先在 ebay 上提出“争议”。
  • 一旦提出争议,我必须等待客户确认 他同意退款(愚蠢,因为他是让我退款的人, 但这就是它在 ebay 上的工作方式)。
  • 此功能获取我打开的所有争议并定期检查其状态以查看客户是否已回复争议。
  • 客户可能同意(然后我退款)或拒绝(然后我回滚)或可能在 7 天内不回复(我自己关闭争议然后退款)。

问题

  1. 如您所见,代码构建在 if/else 结构上,这意味着新状态(例如客户关闭其帐户)将意味着我需要添加 else if 声明,这违反了 开闭原则.
  2. 我感觉这个函数有不同的抽象层。 getRequestedEbayOrdersFromDB() 非常抽象,而其余代码则有很多细节。
  3. 某些函数重复了insertRecordInOrderHistoryTable(),这只是在历史实体表中添加了一条新记录。

解决方案

我想过将多个if/else 转换为工厂模式,但我只使用工厂来创建对象而不改变行为。

接下来我考虑使用策略模式,但未能构建出好的解决方案。

任何帮助表示赞赏。 谢谢。

【问题讨论】:

  • 也许使用“工厂”,但返回闭包而不是对象?这样可以根据状态返回需要执行的例程吗?尽管考虑一下,但您的工厂仍然需要基本相同的if/else 才能做到这一点,所以它可能不会真正为您带来任何好处......
  • 我看不到 $orderline 在您的函数中定义的位置,这是故意的吗? :)
  • @Jack 抱歉这是 $order :D 是因为我简化了我忘记重命名的代码 :P

标签: php design-patterns refactoring


【解决方案1】:

创建一个退款订单处理程序工厂怎么样?

我没有从提供的代码中获得足够的信息,但我假设 order 中有一些东西可以作为处理程序类型的键,因此您可以在 refundAcceptedDisputes 中执行以下操作: (我是 C++ 人,很抱歉伪代码)

refundOrderHandler = RefundOrderHandlerFactory.getHandler(order);
refundOrderHandler.doRefund(); // Name this method accordingly

那么您的工厂将有一个简单的 if/else 来获取处理程序的类型,如下所示:

RefundOrderHandlerFacotry::getHandler(order)) {
  if(isDisputAccepted(order) {
    return handlerA(order);
  }
  else if(isDisputCancelled(order)) {
    return handlerB(order);
  }
  else if(isDisputOlderThan7Days(order)) {
    return handlerC(order);
  }
  // Add new handlers here
}

确定处理程序类型的逻辑必须放在工厂中,或使其可访问。

然后,您必须为每种类型的RefundHandler 创建一个类,其中RefundHandlerBase 作为基类,将具有抽象方法doRefund() 请注意,与退款相关的所有逻辑都包含在相应的类中。要添加更多退款处理程序,您必须创建一个类来处理它,将else if 添加到工厂,以及确定RefundHandler 类型的适当逻辑。

【讨论】:

  • +1 这实际上是我试图通过工厂模式实现的:) 一个问题...返回应该是return new handlerA(order); 对吗?因为我需要对处理程序本身内部的实体进行操作。
  • 是的,创建的对象肯定有顺序,我会相应地更新答案,谢谢。
猜你喜欢
  • 2016-10-13
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 2015-05-26
  • 1970-01-01
  • 2019-08-14
  • 1970-01-01
相关资源
最近更新 更多