この場合、 Visitor デザイン パターンを使用できます。Product
クラスでメソッドを実装し、引数addToBill
として請求書インターフェイスを実装するインスタンスを渡しますIBill
。アイテムで利用可能なすべての必要な情報を受け入れるIBill
メソッドをサポートします。addToTotal
あなたの場合、これは価格です。例えば:
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);
}
...
}
ただし、常に不安定な地面に巻き込まれます。上の例では のようなメソッドが必要ですaddToTotal
。これは不変条件 (合計は、項目の価格と数量の積の合計と一致する必要があります) を導入するものであり、まさに「教えて、聞かないで」というようなことを回避することになっています。あなたはなしでそれを試みることができますaddToTotal
: 合計を追跡します。製品と数量に加えて価格を渡します。合計を更新します。クラスを使用していないか、あまり使用していないため、これはクラスを持つ目的をやや無効にします。これにより、渡された価格と製品が作成されたときに指定された価格が一致する必要があるという不変条件も追加されますが、一致しなくても問題は発生しません (単に奇妙になります)。*インスタンス化しているBill
ShoppingCart
addItem
addItem
LineItem
Product
addItem
Product
そしてLineItem
; addItem
合計を更新します。$price
以前に追加された追加のアイテムを追加する場合、渡された値が以前の呼び出しで渡された量と一致する必要があるという追加の不変条件が存在するか、addItem
単に追加の既存のアイテムを追加できないようにする必要があります。※アイテムはまとめて廃棄してください。ShoppingCart
製品 ID と数量を格納します。を呼び出すたびaddItem
に合計が更新されます。createBill
計算済みの合計を使用します。他のものよりも、これは別々の懸念を結びつけます。
他にも考えられる設計はありますが、いずれも何らかの問題に悩まされています。通常は、関心の分離、不変条件の導入、複雑さの追加に関連しています。全体として、合計を計算するメソッド内で品目の合計価格に直接アクセスすることは、最も簡単であるだけでなく、最もクリーンで、エラーが発生する可能性が最も低くなります。