2010-04-20 52 views
0

附加是一個經典的裝飾模式。我的問題是你將如何修改下面的代碼,以便你可以包裝零或一個頂部的比薩Singleton模式與裝飾器相結合

現在我可以有一個Pepporini - >香腸 - > Pepporini - >比薩類駕駛總成本高達10美元,爲Pepporini收取兩次費用。

我不認爲我想要使用責任鏈模式,因爲順序無關緊要,並不是所有的澆頭都被使用?

謝謝

namespace PizzaDecorator 
{ 
public interface IPizza 
{ 
    double CalculateCost(); 
} 

public class Pizza: IPizza 
{ 
    public Pizza() 
    { 
    } 

    public double CalculateCost() 
    { 
     return 8.00; 
    } 

} 

public abstract class Topping : IPizza 
{ 
    protected IPizza _pizzaItem; 

    public Topping(IPizza pizzaItem) 
    { 
     this._pizzaItem = pizzaItem; 
    } 

    public abstract double CalculateCost(); 

} 

public class Pepporini : Topping 
{ 
    public Pepporini(IPizza pizzaItem) 
     : base(pizzaItem) 
    { 
    } 

    public override double CalculateCost() 
    { 
     return this._pizzaItem.CalculateCost() + 0.50; 
    } 


} 

public class Sausage : Topping 
{ 
    public Sausage(IPizza pizzaItem) 
     : base(pizzaItem) 
    { 
    } 


    public override double CalculateCost() 
    { 
     return this._pizzaItem.CalculateCost() + 1.00; 
    } 
} 

public class Onions : Topping 
{ 
    public Onions(IPizza pizzaItem) 
     : base(pizzaItem) 
    { 
    } 

    public override double CalculateCost() 
    { 
     return this._pizzaItem.CalculateCost() + .25; 
    } 
} 
} 
+0

作業的任何機會? – womp 2010-04-20 20:56:50

+0

不,認爲我隱瞞了「真實」的應用程序,爲了我的工作,但這不僅僅是功課,而是實際上帶來了金錢:) – Mike 2010-04-20 21:01:12

+0

當你開始思考模式時,這表明你過度使用它。 – 2010-04-20 21:08:46

回答

5

我會創建一個Topping類,它會有一個價格,並使你的Pizza類支持多種澆頭。然後,根據每個添加的頂部來計算價格。

public interface IPizza 
{ 
    double CalculateCost(); 
} 

public class Pizza : IPizza 
{ 
    private List<Topping> toppings = new List<Topping>(); 
    private double stdCost; 

    public Pizza(double cost) 
    { 
     // this would be the standard cost of the pizza (before any toppings have been added) 
     stdCost = cost; 
    } 

    public Pizza(IList<Topping> toppings) 
    { 
     this.toppings.AddRange(toppings); 
    } 

    public void AddTopping(Topping topping) 
    { 
     this.toppings.Add(topping); 
    } 

    public void RemoveTopping(Topping topping) 
    { 
     this.toppings.Remove(topping); 
    } 

    public double CalculateCost() 
    { 
     var total = stdCost; 
     foreach (var t in toppings) 
     { 
      total += t.Price; 
     } 
    } 
} 

public class Topping 
{ 
    public Topping(string description, double price) 
    { 
     Description = description; 
     Price = price; 
    } 

    public double Price { get; private set; } 
    public string Description { get; private set; } 
} 

使用

IPizza p = new Pizza(5.00); 
p.AddTopping(new Topping("Pepperoni", 0.50)); 
p.AddTopping(new Topping("Sausage", 0.50)); 
var charge = p.CalculateCost(); // charge = 6.00 
+0

這就是我的建議。在比薩上下文中對我來說非常合乎邏輯。 – Robb 2010-04-20 21:17:01

+0

Mike說他「隱藏了*真實*應用程序」,所以他可能需要單獨的,更復雜的邏輯來支持每個「頂部」而不僅僅是價格。 – 2010-04-20 21:21:49

+0

@BlueRaja:我認爲邁克的意思是*隱藏了他所指的真實應用,而不是提供真實的代碼示例。他正在使用Pizza/Topping關係。 – James 2010-04-20 21:26:23

1

我不會用裝飾圖案出現這種情況。相反,我會比薩持有一套ITopping:

public interface ITopping { 
    double cost(); 
} 

該集將保證沒有重複。現在,要計算一個比薩的成本,你將它的基礎價格加到所有澆頭成本的總和上

+0

+1我會提出同樣的建議,'Toppings'不是'IPizzas',應該用比薩餅來引用,而不是反過來。 (這可能只是由於Mike「隱藏了真正的應用程序」,在這種情況下,我們需要看到真正的類層次結構來幫助您進一步實現)。 – 2010-04-20 21:10:48

+0

「ITopping」的目的是什麼?我真的不覺得需要上述設計來完成子類「Topping」。我認爲一個包含價格/描述的簡單的「Topping」類會很有用。 – James 2010-04-20 21:17:11