首先设计模式:装饰者行为令人费解

时间:2010-06-24 14:48:43

标签: java design-patterns

这是关于代码行为的问题,而不是模式本身。我将列出下面的代码

  public abstract class Beverage {
    protected String description;

    public String getDescription(){
        return description;
    }
    public abstract BigDecimal cost();
}


public abstract class CondimentDecorator extends Beverage{
    @Override
    public abstract String getDescription();
}

public class HouseBlend extends Beverage{

    public HouseBlend() {
        description = "House Blend";
    }

    @Override
    public BigDecimal cost() {
        return BigDecimal.valueOf(.89);
    }

}

public class Mocha extends CondimentDecorator{
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        System.out.println("desc: " + beverage.getDescription());
        return beverage.getDescription() + ", Mocha";
    }

    @Override
    public BigDecimal cost() {
        System.out.println("bev: "+beverage.cost());
        return BigDecimal.valueOf(.20).add(beverage.cost());
    }

}

public class CoffeeTest {
        public static void main(String args[]){
            Beverage blend = new HouseBlend();
            blend = new Mocha(blend);
            blend = new Mocha(blend);
            blend = new Mocha(blend);
            System.out.println(blend.getDescription() + " * "+blend.cost());
        }
}

当CoffeeTest运行时,我得到以下输出,我想了解

1    desc: House Blend
2    desc: House Blend, Mocha
3    desc: House Blend
4    desc: House Blend, Mocha, Mocha
5    desc: House Blend
6    desc: House Blend, Mocha
7    desc: House Blend
8    bev: 0.89
9    bev: 1.09
10    bev: 0.89
11    bev: 1.29
12    bev: 0.89
13    bev: 1.09
14    bev: 0.89
15    House Blend, Mocha, Mocha, Mocha * 1.49

所以这些是我的问题:

  1. 我预计'desc'和'bev'会被打印3次,那么为什么xtra线呢?
  2. 当没有明确的状态保存时,如何打印'House Blend,Mocha,Mocha'?
  3. 我对“费用”有同样的问题,beverage.cost()如何通过添加金额来节省费用。
  4. 我确信答案在于Beverage和CondimentDecorator之间的多态性。

3 个答案:

答案 0 :(得分:4)

  

当没有明确的状态保存时,如何打印'House Blend,Mocha,Mocha'?

您正在创建3个不同的对象。我们称他们为a,b和c。所以我们可以重写代码看起来像这样:

Beverage a = new HouseBlend();
Beverage b = new Mocha(a);
Beverage c = new Mocha(b);
System.out.println(c.getDescription() + " * "+c.cost());

它将与您的代码执行相同的操作,但您更清楚的是您正在处理3个不同的对象。分配

blend = new Mocha(blend);

不会替换对象,但实际上会创建一个新对象,只需将引用混合修改为新对象。

当您在代码中调用blend.getDescription()时,您指的是对象c,它调用对象b的getDescription,它调用对象a的getDescription。对象a的getDescription()返回字符串“House Blend”。因此,对象b的getDescription()返回“House Blend,Mocha”。然后对象c的getDescription()返回“House Blend,Mocha,Mocha”。

getCost()发生了类似的事情。

答案 1 :(得分:0)

在Mocha.getDescription中你有System.out.println并且你会返回一些东西,你也会在void main中打印。但是我得到以下内容:
desc:House Blend
desc:House Blend,Mocha
desc:House Blend
bev:0.89
bev:1.09
bev:0.89
House Blend,Mocha,Mocha * 1.29
如果在void main中你有三次新的Mocha,那么输出就像你的那样

public static void main(String[] args) {
        Beverage blend = new HouseBlend();
        blend = new Mocha(blend);
        blend = new Mocha(blend);
        blend = new Mocha(blend);
        System.out.println(blend.getDescription() + " * "+blend.cost());
}

装饰器模式就像在物体周围包裹物体一样,它就像: HouseBlend has_a(摩卡has_a(摩卡has_a(摩卡)))

答案 2 :(得分:0)

在getDescription中,您调用drink.getDescription()两次,两次都打印行。