web-dev-qa-db-ja.com

この例のSOLID原則の使用方法

先週、SOLIDの原則について読んで、それらを使用して現実世界の問題を解決しようとすることを決心しました。したがって、合計を管理する現実世界のeコマースサイトの問題が発生しました。

問題ステートメント:小計、税金、バウチャー、クーポン、カート製品の合計などの合計を計算する必要があります。

そこで、total_dataとtotalをプログラムの残りの部分に返すTotalManagerを作成することにしました。

_// total data variable looks like
array('key'=>value)
_

例えばarray('subtotal'=>100,'total'=>150,'tax'=>50)

_    class TotalManager{
        private $total_data;
        public function get_total_data()
        {
            $totals = array('subtotal','total','taxes')         
            // foreach totals array gets each object check its instance of interface itotal and called it's get method.
        }        
    }

    Interface Itotal
    {
        public function get_total_data();
        public function get_total();
    }    

    class subtotal implements Itotal
    {
        public function get_total_data()
        {
            // it needs cart object
            // get the cart product calculate totals and return total_data and total 
        }
        public function get_total()
        {
            return the subtotal in double/float
        }
    }

    class total implements Itotal
    {
        public function get_total_data()
        {
            // get the other totals object  and calls it get_total method
            // calulate sum of all totals and return 
        }

        public function get_total()
        {
            // calculate total and return back;
        }
    }
_

しかし、私はこのモデルで問題に直面しています:

依存関係の逆転の原則では、カートまたは小計のオブジェクトを小計で直接作成することはできません。合計クラスはそれぞれ、Total Managerのコントローラーから渡す必要があります。

それを考えるとき、クラスを追加するときはいつでも、Total Managerを変更して新しいメソッドを追加する必要があるため、オープン/クローズの原則に違反しています。これをOODで解決する方法は?

6
siddhesh

私はあなたがphpを使用していることを確認し、psrコーディングスタイルに固執しようとします: psr-1 および psr-2


デコレータパターンを調べます。これは、このような状況で一般的に使用されるパターンです。


カート内のアイテムを表すために使用される、ある種のLineItemクラスがあると思います。それらはおそらく次のようになります。

_interface LineItem
{
    public function getPrice();
}
_

次に、製品の実装:

_class ProductLineItem implements LineItem
{
    public function __construct(Product $product, $quantity) {
        $this->product = $product;
        $this->quantity = $quantity;
    }

    public function getPrice()
    {
        return $this->quantity * $this->product->getPrice();
    }
}
_

次に、抽象デコレータを作成します。

_abstract class LineItemDecorator implements LineItem
{
    public function __construct(LineItem $item) {
        $this->item = $item;
    }

    public function getPrice()
    {
        return $this->item->getPrice(); //delegation
    }
}
_

この抽象クラスは必要ありません。 1つの場所でのみすべてをベースオブジェクトに委任するために使用する傾向があります。複数のメソッドが存在する場合に特に役立ちます。

また、Decoratorが同じインターフェイスをどのように実装するかに注意してください!

そして今こそ割引の時間です:

_class DiscountLineITemDecorator extends LineItemDecorator 
{
    public function getPrice()
    {
        return $this->item->getPrice() * 0.75;
    }
}
_

次に、それを使用します。

_$lineItem = new ProductLineItem($theProduct, 2);
$lineItemWithDiscount= new DiscountLineITemDecorator($lineItem);
//lets add it to our cart
$cart->addLineItem($lineItemWithDiscount);
_

カートには、おそらくgetPrice()メソッドもあります。おそらく次のようになります。

_foreach ($this->lineITems as $lineItem) {
    $price += $lineItem->getPrice();
}
return $price;
_

では、カート全体の割引についてはどうでしょうか?

_$cartWithDiscount = new DiscountCartDecorator($cart);
_

そしてブーム

_$cartWithDiscount->getPrice();
_

ここで使用されるすべてのコードは例として役立ちます。ネーミングは大幅に改善できるので、自由に編集してください!

1
Pinoniq