【问题标题】:Singleton Pattern combine with a Decorator单例模式与装饰器结合
【发布时间】:2010-04-20 20:55:57
【问题描述】:

Attached 是一个经典的装饰器模式。我的问题是你将如何修改下面的代码,以便你可以将每个配料中的零个或一个包装到比萨饼上

现在我可以吃 Pepporini -> Sausage --> Pepporini --> Pizza 课,总成本高达 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;
    }  
}
}

【问题讨论】:

  • 不,我承认我隐藏了“真正的”应用程序,为了我的工作,但这不仅仅是家庭作业,这实际上带来了金钱:)
  • 当你开始以模式思考时,这表明你做得过火了。

标签: c# design-patterns


【解决方案1】:

我会创建一个 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;
        }
        return total;
    }
}

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

【讨论】:

  • 这就是我的建议。在 Pizza 环境中对我来说非常合乎逻辑。
  • Mike 说他“隐藏了真正的应用程序”,所以他可能实际上需要为每个“topping”单独的、更复杂的逻辑,而不仅仅是一个价格。
  • @BlueRaja:我认为 Mike 的意思是 隐藏真正的应用程序,他指的是不提供真正的代码示例。他使用的是 Pizza/Topping 关系。
【解决方案2】:

我不会在这种情况下使用装饰器模式。相反,我会在披萨上放一组 ITopping:

public interface ITopping {
    double cost();
}

该集合将保证没有重复。现在,要计算披萨的成本,您需要将其基本价格加到所有配料成本的总和中

【讨论】:

  • +1 我打算提出同样的建议,Toppings 不是 IPizzas,应该由 ha Pizza 引用,而不是相反。 (这可能仅仅是因为 Mike 的“隐藏了真实的应用程序”,在这种情况下,我们需要查看真实的类层次结构以进一步帮助您)。
  • ITopping 的目的是什么?我根本不认为上述设计需要子类Topping。我认为包含价格/描述的简单 Topping 类就足够了。
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 2013-12-06
  • 2011-01-16
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
相关资源
最近更新 更多