2011-09-13 21 views
2

PHPで書かれたショッピングカートの合計を計算する方法を検討しています。さまざまな条件を処理するための良いデザインパターンに関するフィードバックがあります。私は管理者に割引を計算するための複数の戦略を提供しようとしています。管理者は、税金が適用される前または後に割引を適用するか、配送料に割引を適用するかを選択することができます。これは私の仕事の概要を示しています。複数の変数のステータスに基づいた条件文の良いデザインパターン

変数

私は可能な値と、このタスクのために、以下の変数があります。

$tax_optionを:

$shipping_option 'の後に'、 '前': 'はい'、「いいえ'

これらの2つの変数の他に、合計値を計算する式は、$subtotal(カート内のアイテムの量)と$reduction(割引総額)を入力します。

一般的に言えば、$tax_option$shipping_option変数の4つの組み合わせごとにテストします。 $subtotal$reduction以下である場合の式を変更する必要もあります。私には8つの異なる条件があります。 if文、switch声明、または戦略パターン:私は私は本当にここ3異なるオプションを持っていることを把握

可能性

ifステートメントとストラテジパターンの構造を示しますが、switchの可能性は除外されます。なぜなら、この文脈では正しいとは思えないからです。ここで

if

私は検討していますif文の一般的なパターンです。私はこれをわずかに再構成できることを知っていることに注意してください。何らかの理由でこれは私にとって読みやすいものです。

if($tax_option == 'after' && $shipping_option == 'yes') 
{ 
    if($subtotal <= $reduction) 
    { 

    } 
    else 
    { 

    } 
} 
elseif($tax_option == 'before' && $shipping_option == 'yes') 
{ 
    if($subtotal <= $reduction) 
    { 

    } 
    else 
    { 

    } 
} 
elseif($tax_option == 'before' && $shipping_option == 'no') 
{ 
    if($subtotal <= $reduction) 
    { 

    } 
    else 
    { 

    } 
} 
elseif($tax_option == 'after' && $shipping_option == 'no') 
{ 
    if($subtotal <= $reduction) 
    { 

    } 
    else 
    { 

    } 
} 
else 
    $new_total = $total; 

Strategyパターン

この問題の解決のためのオンライン周りを探した後、私は素晴らしい見えた、Strategy Patternについて学びました。私はここで作業を開始し、それに関するいくつかのフィードバックを気にしません。これまでのところ、いくつかのルーチンを明白に削除して、次のコードのように見えます。

class DPPCalculateTotal 
{ 
    protected $formulas = array(); 

    public function DPPCalculateTotal($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 
     foreach($this->formulas as $formula) 
     { 
      if($formula->test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction)) 
      { 
       return $formula->calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction); 
      } 
     } 
    } 

    function add_formula(DPPFormula $formula) 
    { 
     $this->formulas = $formula; 
    } 
} 

interface DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction); 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction); 
} 

class AfterTaxesYesShippingGreaterSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class AfterTaxesYesShippingLesserSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class AfterTaxesNoShippingGreaterSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class AfterTaxesNoShippingLesserSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class BeforeTaxesYesShippingGreaterSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class BeforeTaxesYesShippingLesserSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class BeforeTaxesNoShippingGreaterSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

class BeforeTaxesNoShippingLesserSubotal implements DPPFormula 
{ 
    public function test($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 

    public function calculate_total($tax_option, $shipping_option, $total, $subtotal, $shipping, $tax, $coupons_amount, $reduction) 
    { 

    } 
} 

あなたの意見で質問

1)、ここで何が続行するための最良の方法だろうか?

2)この場合の戦略パターンの利点は何ですか?

3)戦略パターンを試してみるのは初めてですが、正しい方向に向かっているように見えますか?

は、あなたの入力をありがとうございました!私はこのパターンを学ぶのが楽しいですし、私が得ることができるフィードバックを感謝します!

+0

個々の数式があまり複雑でない場合は、if文を探します。特にあなたがそれをより読みやすいと思うならば。 if文の中に$ shipping_option == 'yes'を入れれば、評価が減ります。 –

答えて

3

私は正しい方向に向かっていると思います。戦略パターンを使用すると、アプリケーションが大きくなったり要件が変わったりすると、後で新しい戦略を追加するのは簡単です(私の経験では10回のうち9回です)。

私が示唆しているのは、Orderという名前のクラスをもう1つ作成してそこにすべての注文の詳細をカプセル化し、代わりにオブジェクトを渡すことです。あなたのテストや計算方法は、あなたの複雑さに応じてあなたがまたはOrderためのインターフェイスを使用したくない場合があり

interface DPPFormula 
{ 
    public function test(OrderInteface $order); 

    public function calculate_total(OrderInterface $order); 
} 

interface OrderInterface 
{ 
    function setTotal($total); 
    function getTotal(); 
} 

あなたは、同様の何かができる

$order->setTotal($calculator->DPPCalculateTotal()); 

にビット整然とだろう。抽象度をさらに高めるために、1つを使用することを強くお勧めします。

+0

gildenの提案に感謝します!物事が変わるにつれてこれが簡単になることについて、私はこのヒントを感謝します。私はそれを考えていませんでしたが、2つの方法を見て、私はすでに戦略パターンが大きな利点を持っていることを知ることができます。私は実際に既存のシステムを構築しているので、そのロジックは既に処理されているので(注文がうまくいっている)、注文インタフェースを構築することはありませんが、素晴らしい提案に感謝します。 – tollmanz

0

私は、トータルをディスカウント可能な量とディスカウント可能でない量に分けることができると思います。次に割引額に割引を適用し、残りの部分にこの擬似コードを追加します。

extra = 0 
if (tax_option) 
    subtotal += tax(subtotal) 
else 
    extra += tax(subtotal) 
if (delivery_option) 
    subtotal += delivery 
else 
    extra += delivery 
if (subtotal > reduction) 
    subtotal -= reduction 
else 
    // stuff here 
subtotal += extra 
+0

ありがとうNeil!ここで問題となるのは、言及された変数の状態によって式が変わるということです。たとえば、管理者が税引き前と配送時に割引を適用したい場合、数式は少し狂ったものになります。また、割引が小計と等しい場合は、合計を0にすることを検討する必要があります。しかし、1人の管理者は、ディスカウントが配送に適用されないため、配送料を請求することがあります。これは本当に速い混乱になる方法を参照してください? – tollmanz

+1

@Sardineあなたはadd_tax、add_shipping、apply_discountというメソッドを必要としていて、それらを適切な順序で適用するようです。おそらく、これは戦略パターンを使用して行うことが可能です。多分誰かがそれをやる方法を考え出すでしょう。 – Neil

+0

ニール...私は全く同意します。問題は、ひどく混乱しているシステムに接続していることです。私のコードは、すでに計算された値を取り、それらの値に基づいて新しい合計を計算することを意図しています。私はシステム全体が書き直されることを願っています。 – tollmanz

-1

ルックアップテーブル/アレイの使用について考えましたか?物事を誰かに少し明瞭にするかもしれない。配列キーは、さまざまな組み合わせの文字列にすることができます。次に、任意の値を検索キーに関連付けることができます。

$lookup = array(
    'taxo-after:shipo-yes'=> array('reduction'=>100), 
    'taxo-after:shipo-no'=> array('reduction'=>100), 
    'taxo-before:shipo-yes'=> array('reduction'=>100), 
    'taxo-before:shipo-no'=> array('reduction'=>100), 
    ... 
); 

$lookup_key = 'taxo-'.$tax_option.':'.'shipo-'.$shipping_option; 
if ($subtotal < $lookup[$lookup_key]['reduction']) { 
} else { 
} 

これは、最初のコード例全体をほとんど置き換えます。 1配列宣言と1 if文。パフォーマンスのペナルティやコードの数を増やすことなく、100の可能性を追加できます。

+0

私はこの方法を考えていませんでした。残念ながら、一致条件に基づいて数式を適用することはできません。 – tollmanz

関連する問題