2

誰かがこの関数のデザインパターンまたはより良い実装ソリューションを提供できるかどうか疑問に思いました:

  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構造に基づいて構築されています。つまり、新しいステータス(たとえば、顧客がアカウントを閉鎖する)は、OpenClosedPrincipleに違反するステートメントを追加する必要があることを意味else ifます。
  2. 関数にはさまざまな抽象化レイヤーがあるように感じます。getRequestedEbayOrdersFromDB()コードの残りの部分には多くの詳細がありますが、は非常に抽象的です。
  3. 一部の関数が繰り返さinsertRecordInOrderHistoryTable()れ、履歴エンティティテーブルに新しいレコードが追加されるだけです。

解決

if/else倍数をファクトリパターンに変換することを考えましたが、ファクトリを使用してオブジェクトを作成し、動作を変更しませんでした。

次に、戦略パターンを使用することを考えましたが、良いソリューションを構築できませんでした。

どんな助けでもありがたいです。ありがとう。

4

1 に答える 1

3

払い戻し注文ハンドラーのファクトリーを作成するのはどうですか?

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タイプごとにクラスを作成する必要が あります。払い戻しに関連するすべてのロジックが適切なクラスに含まれていることに注意してください。払い戻しハンドラーをさらに追加するには、それを処理するクラスを作成し、ファクトリにを追加し、のタイプを決定するための適切なロジックを追加する必要があります。RefundHandlerBasedoRefund()else ifRefundHandler

于 2012-04-23T13:30:46.077 に答える