views:

136

answers:

3

This is a question on the behavior of the code rather then the pattern itself. I will lay out the code below

  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());
        }
}

When CoffeeTest is run I get the following output which I would like to understand

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

So these are my questions:

  1. I expected 'desc' and 'bev' to be printed 3x, so why the xtra lines?
  2. How is 'House Blend, Mocha, Mocha' printed when there is no explicit state saved?
  3. I have the same question about 'cost', how is beverage.cost() saving state by adding the amounts.

I am sure the answers lie in polymorphism between Beverage and CondimentDecorator.

A: 

Hi, in Mocha.getDescription you have System.out.println and addiotionally you return something, that you print also in the void main. but nevertheless I get the following:
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
if in void main you have three times new Mocha the output looks like yours

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());
}

decorator pattern works like wrapping objects around objects here it is like:
HouseBlend has_a ( Mocha has_a ( Mocha has_a ( Mocha ) ) )

Oops
A: 

In getDescription, you call beverage.getDescription() twice, both of which print lines.

Sjoerd
+4  A: 

How is 'House Blend, Mocha, Mocha' printed when there is no explicit state saved?

You are creating 3 distinct objects. Let us call them a, b and c. So we can rewrite the code to look like this:

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

which will do the same thing as your code but it is clearer that you are dealing with 3 different objects. Assigning

blend = new Mocha(blend);

does not replace the object but actually creates a new object and simply modifies the reference blend to the new object.

When you call blend.getDescription() in your code you are referring to object c, which calls getDescription of object b which calls getDescription of object a. The getDescription() of object a returns the String "House Blend". So, getDescription() of object b returns "House Blend, Mocha". And getDescription() of object c then returns "House Blend, Mocha, Mocha".

A very similar thing happens to getCost().

Vincent Ramdhanie