Come utilizzare i principi SOLID in questo esempio

6

Ho letto i principi SOLID la settimana scorsa e ho deciso di provare a risolvere il problema del mondo reale usandoli. Quindi ho ottenuto il problema dei totali di gestione del sito di e-commerce del mondo reale.

Dichiarazione del problema:   Dobbiamo calcolare alcuni totali come subtotale, tasse, buoni, coupon, totale su un carrello prodotti.

Quindi ho deciso di fare TotalManager che restituisce total_data e total al resto del programma.

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

es. 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;
        }
    }

Ma sto affrontando problemi in questo modello:

Per il principio dell'inversione delle dipendenze non posso creare direttamente l'oggetto del carrello o del totale parziale in subtotale, classe Total, ma devo passarli dal controller al gestore totale.

Quando ci penso, ogni volta che aggiungo la classe, devo cambiare il gestore totale per aggiungere il nuovo metodo in modo da violare i principi di apertura / chiusura. Come risolvere questo in OOD?

    
posta siddhesh 12.07.2015 - 08:58
fonte

2 risposte

1

Vedo che usi php, prova ad attenersi agli stili di codifica di psr: psr-1 e psr-2 .

Guarda nello schema del decoratore. questo è un pattern comunemente usato in questo tipo di situazioni.

Probabilmente hai una sorta di classe LineItem che viene utilizzata per rappresentare gli elementi nel tuo carrello. Probabilmente hanno un aspetto simile a questo:

interface LineItem
{
    public function getPrice();
}

Con quindi un'implementazione per il tuo prodotto:

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();
    }
}

Ora è il momento di creare il nostro decoratore astratto:

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

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

this abstract class is not needed. I just tend to use it to delegate everything to the base object only in one place. Especially useful if multiple methods exist.

Note also how my Decorator implements the same interface!

E ora è il momento per i nostri sconti:

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

Saremmo quindi in grado di usarlo:

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

Il nostro carrello probabilmente ha anche un metodo getPrice() . Probabilmente sarà simile a questo:

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

Quindi, per quanto riguarda lo sconto su un intero carrello?

$cartWithDiscount = new DiscountCartDecorator($cart);

e boom

$cartWithDiscount->getPrice();

All code used here serves as an example. The naming can be improved a lot, so feel free to edit!

    
risposta data 14.07.2015 - 13:03
fonte
-2

Il principio Apri / Chiuso consente di aggiungere nuovi metodi. Non sarai in grado di modificare l'interfaccia con i metodi esistenti.

Potrebbe essere più semplice avere una classe che prende un carrello e restituisce / ricalcola i totali. Cerca di evitare l'uso di questa classe per mantenere lo stato tra una chiamata e l'altra.

    
risposta data 12.07.2015 - 13:42
fonte