Można użyć Visitor design pattern w tym przypadku. W swojej klasie Product
zaimplementuj metodę addToBill
i jako argument przeprowadź instancję implementującą interfejs twojego rachunku, IBill
. IBill
obsługuje metodę addToTotal
, która będzie akceptować wszystkie potrzebne informacje dostępne w elemencie; w twoim przypadku jest to cena. Na przykład:
interface IBill {
/* needs to be public because PHP doesn't understand the concept of
friendship
*/
function addToTotal($price);
}
class Bill implements IBill {
private $total = 0;
function addToTotal($price) {
$this->total += $price;
}
...
}
class ShoppingCart {
private $items = array();
function addItem($id, $product, $quantity) {
if (isset($this->items[$id])) {
$this->items[$id]->addQuantity($quantity);
} else {
$this->items[$id] = new LineItem($product, $quantity);
}
}
private createBill() {
$bill = new Bill;
foreach ($this->items AS $lineItem) {
$lineItem->addToBill($bill);
}
return ...;
}
}
class LineItem {
private $product, $quantity;
function __constructor($product, $quantity) {...}
function addToBill(IBill $bill) {
$this->product->addToBill($bill, $quantity);
}
function addQuantity($quantity) {
$this->quantity += $quantity;
}
...
}
class Product {
private $name, $description, $price;
function __constructor(...) {...}
function addToBill(IBill $bill, $quantity) {
$bill->addToTotal($this->price * $quantity);
}
...
}
Jednak zawsze lądujesz na chybotliwym terenie. Powyższe wymaga metody, takiej jak addToTotal
, która wprowadza niezmiennik (suma musi pasować do sumy produktów ceny i ilości elementów zamówienia), należy unikać takich rzeczy, jak "Powiedz, nie pytaj". Możesz spróbować zrobić to bez addToTotal
: * Zlikwiduj numer Bill
; ShoppingCart
śledzi całkowitą. Przekaż cenę do addItem
oprócz produktu & ilość; addItem
aktualizuje sumę. To nieco pogarsza cel posiadania klas, ponieważ nie używasz zbyt wiele.Dodaje to również niezmienność, że przekazana cena i cena podane podczas tworzenia produktu powinny być zgodne, ale jeśli nie, to nie powinno powodować problemów (byłoby to po prostu dziwne). * Czy addItem
utworzyć instancję Product
i LineItem
; addItem
aktualizuje sumę. Podczas dodawania dodatkowych elementów, które zostały wcześniej dodane, musi istnieć dodatkowy niezmiennik, który musi być zgodny z wartością przekazaną w poprzednich połączeniach, lub addItem
po prostu nie może dodawać dodatkowych, istniejących elementów. * Pozbądź się wszystkich razem. ShoppingCart
przechowuje identyfikator produktu i ilość. Każde połączenie z numerem addItem
aktualizuje sumę. createBill
używa już obliczonej sumy. Nawet więcej niż inne, to jednoczy separate concerns.
Istnieją inne potencjalne projekty, ale każdy cierpi z powodu jakiegoś problemu, zazwyczaj związanego z separacją obaw, wprowadzaniem niezmienników i zwiększaniem złożoności. Łącznie dostęp do całkowitej ceny elementu zamówienia bezpośrednio w metodzie, która oblicza sumę, jest nie tylko najprostszy, ale najczystszy i najmniej prawdopodobny do wygenerowania błędów.
jeśli koszyk zawiera alistę przedmiotów, dlaczego zakup koszykówki nie jest w stanie nauczyć się wartości jego poszczególnych przedmiotów? – user12345613
po stwierdzeniu "Nie pytaj" - uwaga wydaje się zła. – Tom
Gdzie usłyszałeś zasadę "powiedz, nie pytaj"? Nigdy o tym nie słyszałem. – xxpor