装饰模式问题C#/ java

时间:2010-12-02 09:31:11

标签: c# java design-patterns decorator

我正在查看this维基百科的文章,并且无法理解这是怎么回事。有点沮丧只是通过查看它无法理解代码,我决定将代码移植到c#(我是.net,对不起家伙:))。只需要一些小修改(继承和扩展,基于超级等)并运行应用程序。令我惊讶的是,我得到了以下输出:

Cost: 1 Ingredient: Coffee
Cost: 1 Ingredient: Coffee
Cost: 1 Ingredient: Coffee
Cost: 1 Ingredient: Coffee

只是好奇,任何java开发都可以告诉我这里有什么不同以及为什么维基百科示例有效(如果它确实有效,就像它们所说的那样)。

    namespace ConsoleApplication1
{
 class Program
 {
  static void Main(string[] args)
  {

  Coffee sampleCoffee = new SimpleCoffee();
  Console.WriteLine("Cost: " + sampleCoffee.getCost() + " Ingredient: " + sampleCoffee.getIngredient());

        sampleCoffee = new Milk(sampleCoffee);
        Console.WriteLine("Cost: " + sampleCoffee.getCost() + " Ingredient: " + sampleCoffee.getIngredient());

        sampleCoffee = new Sprinkles(sampleCoffee);
        Console.WriteLine("Cost: " + sampleCoffee.getCost() + " Ingredient: " + sampleCoffee.getIngredient());

        sampleCoffee = new Whip(sampleCoffee);
        Console.WriteLine("Cost: " + sampleCoffee.getCost() + " Ingredient: " + sampleCoffee.getIngredient());

   Console.ReadKey();

  }
 }



//The Coffee Interface defines the functionality of Coffee implemented by decorator
public interface Coffee
{

    double getCost(); // returns the cost of coffee

    String getIngredient(); //returns the ingredients mixed with coffee
}

//implementation of simple coffee without any extra ingredients
public class SimpleCoffee : Coffee
{

    double cost;
    String ingredient;

    public SimpleCoffee()
    {
        cost = 1;
        ingredient = "Coffee";
    }

    public double getCost()
    {
        return cost;
    }

    public String getIngredient()
    {
        return ingredient;
    }
}



//abstract decorator class - note that it implements coffee interface
abstract public class CoffeeDecorator : Coffee
{

    protected Coffee decoratedCoffee;
    protected String ingredientSeparator;

    public CoffeeDecorator(Coffee decoratedCoffee)
    {
        this.decoratedCoffee = decoratedCoffee;
        ingredientSeparator = ", ";
    }

 public CoffeeDecorator()
 {

 }

    public double getCost() //note it implements the getCost function defined in interface Coffee
    {
        return decoratedCoffee.getCost();
    }

    public String getIngredient()
    {
        return decoratedCoffee.getIngredient();
    }
}

//Decorator Milk that mixes milk with coffee
//note it extends CoffeeDecorator
public class Milk : CoffeeDecorator
{

    double cost;
    String ingredient;

    public Milk(Coffee decoratedCoffee) : base(decoratedCoffee)
    {
        cost = 0.5;
        ingredient = "Milk";
    }

    public double getCost()
    {
        return base.getCost() + cost;
    }

    public String getIngredient()
    {
        return base.getIngredient() + base.ingredientSeparator + ingredient;
    }
}

//Decorator Whip that mixes whip with coffee
//note it extends CoffeeDecorator
public class Whip : CoffeeDecorator
{

    double cost;
    String ingredient;

 public Whip(Coffee decoratedCoffee)
  : base(decoratedCoffee)
    {
        cost = 0.7;
        ingredient = "Whip";
    }

    public double getCost()
    {
        return base.getCost() + cost;
    }

    public String getIngredient()
    {
        return base.getIngredient() + base.ingredientSeparator + ingredient;
    }
}

//Decorator Sprinkles that mixes sprinkles with coffee
//note it extends CoffeeDecorator
public class Sprinkles : CoffeeDecorator
{

    double cost;
    String ingredient;

    public Sprinkles(Coffee decoratedCoffee) : base(decoratedCoffee)
    {

        cost = 0.2;
        ingredient = "Sprinkles";
    }

    public double getCost()
    {
  return base.getCost() + cost;
    }

    public String getIngredient()
    {
  return base.getIngredient() + base.ingredientSeparator + ingredient;
    }
}

}

4 个答案:

答案 0 :(得分:10)

是 - 默认情况下,方法在Java中是虚拟的,但在C#中则不是。

编译代码时,您应该收到警告,谈论“新”修饰符。那应该给你一个线索。目前,Milk(等)方法隐藏阴影 CoffeeDecorator中的方法 - 它们不会被多态调用。

您需要使用CoffeeDecorator修饰符虚拟virtual方法,然后使用Milk修饰符在override(等)中明确覆盖它们。< / p>

// In CoffeeDecorator
public virtual double getCost()
{
    return decoratedCoffee.getCost();
}

// In Milk
public override double getCost()
{
    return base.getCost() + cost;
}

答案 1 :(得分:2)

您忘记声明getCost和getIngredient virtual并在派生版本中使用override关键字。你这样做的方式,只是“超载”方法。

答案 2 :(得分:0)

你正在使用CoffeeDecorator的getCost()方法,而不是实现类'getCost()方法..你需要看一下你如何覆盖该方法。

答案 3 :(得分:0)

这是一个有点冗长的例子,但我想我可以解释两行中的模式。 Decorator模式允许您包装现有的接口实现。 该模式的其他名称是包装器。

例如,您有界面Foo:

interface Foo {
    public int foo();
}

class SimpleFoo implements Foo {
    public int foo() {
        return 1;
    }
}

SimpleFoo.foo()始终返回1;

这是简单的decarator:

class DoubleFoo implements Foo {
    private Foo payload;
    public DoubleFoo(Foo payload) {
        this.payload = payload;
    }
    public int foo() {
        return 2 * payload.foo();
    }
}

DoubleFoo.foo()装饰有效载荷Foo。它将结果乘以2.

显然,它也可以通过自己的实现替换有效载荷的实现。但这不是典型的模式。

使用这种模式最着名的例子是java中的IO:流,读者和编写者都是包装器。例如,BufferedReader为有效负载读取器添加功能:它将数据读取到缓冲区。