Head First Design Patterns: загадочное поведение декоратора - PullRequest
3 голосов
/ 24 июня 2010

Это вопрос поведения кода, а не самого шаблона.Я выложу код ниже

  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() сохраняет состояние, добавляясуммы.

Я уверен, что ответы лежат в полиморфизме между Beverage и CondimentDecorator.

Ответы [ 3 ]

4 голосов
/ 24 июня 2010

Как печатается «House Blend, Mocha, Mocha», когда нет сохраненного явного состояния?

Вы создаете 3 разных объекта.Давайте назовем их а, б и в.Таким образом, мы можем переписать код так:

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, который вызывает getDescription объекта b, который вызывает getDescription объекта a.GetDescription () объекта a возвращает строку «House Blend».Итак, getDescription () объекта b возвращает «House Blend, Mocha».И getDescription () объекта c затем возвращает «House Blend, Mocha, Mocha».

С getCost () происходит нечто похожее.

0 голосов
/ 24 июня 2010

В getDescription вы вызываете beverage.getDescription () дважды, обе из которых печатают строки.

0 голосов
/ 24 июня 2010

в 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 (мокко)))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...