. Product addToBill, , , IBill. IBill addToTotal, , ; . :
interface IBill {
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);
}
...
}
, . , addToTotal, ( ), "Tell, Do not Ask" , addToTotal:
* Bill; ShoppingCart . addItem ; addItem . , LineItem Product . , , , , , , ( ).
* addItem Product LineItem; addItem . , , , $price , , addItem , .
* . ShoppingCart . addItem . createBill . , , .
There are other potential projects, but each of them suffers from some kind of problem, usually associated with the separation of problems, the introduction of invariants and complexity. In aggregate, access to the total price of a position directly inside a method that calculates the total amount is not only the simplest, but the cleanest and least likely to cause errors.