2016-12-29 89 views
3

我目前正在讀的書Head First Design Patterns,並在裝飾一章有下面的例子裏:功能抽象裝飾類,而不是裝飾

Example diagram

書中CondimentDecorator類被描述爲一個abstract decorator。下面是代碼例如:

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

所以基本上裏面只有這迫使所有子類從飲料類重寫getDescription()方法的抽象方法。

這裏是代碼示例摩卡類作爲decorator

public class Mocha extends CondimentDecorator { 
    Beverage beverage; 

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

    public String getDescription() { 
     return beverage.getDescription() + ", Mocha"; 
    } 

    public double cost() { 
     return .20 + beverage.cost(); 
    } 
} 

其他裝飾(類,大豆類...)具有完全相同的代碼,除了硬編碼的成本數(0.20)和名稱(「摩卡」)。

然後我們通過將前一個對象傳入新的裝飾器來使用這個裝飾器模式。

Beverage beverage = new DarkRoast(); 
beverage = new Mocha(beverage); 
beverage = new Mocha(beverage); 
beverage = new Whip(beverage); 

我的問題是,爲什麼不能簡單地從裝飾移動複製功能,以抽象的裝飾?下面是我重構這個例子的方法。

摘要裝飾:

public abstract class CondimentDecorator extends Beverage { 
    private Beverage beverage; 

    protected CondimentDecorator(Beverage previousBeverage) { 
     this.beverage = previousBeverage; 
    } 

    @Override 
    public String getDescription() { 
     return beverage.getDescription() + ", " + getAdditionName(); 
    } 

    @Override 
    public double cost() { 
     return beverage.cost() + getAdditionCost(); 
    } 

    public abstract String getAdditionName(); 
    public abstract double getAdditionCost(); 
} 

裝飾代碼:

public class Mocha extends CondimentDecorator { 
    public Mocha(Beverage beverage) { 
     super(beverage); 
    } 

    @Override 
    public String getAdditionName() { 
     return "Mocha"; 
    } 

    @Override 
    public double getAdditionCost() { 
     return 0.20; 
    } 
} 

現在對每一個新的裝飾我創造我不得不通過構造函數父類的構造提供了先前的飲料對象,我需要覆蓋只返回特定裝飾器的唯一值的方法。

註釋代碼段是正常的嗎?或者,如果我在抽象裝飾器中有功能,它是否完全改變了Decorator模式的要點?

+1

你基本上是問你是否正在改變裝飾模式的使用點,如果你修改它的實現。反而問 - 裝飾者模式的重點是什麼?如果你饒有興趣,你會發現你還有飲料裝飾者,無論是否有你的編輯。 –

回答

1

這段代碼就好了。教科書通常(?)在他們的例子中提供了不完美的代碼,因此他們可以專注於一個特定的概念(在這種情況下是裝飾器)並且不會引起對其他細節的關注。事實上,你找到了一種改進本書代碼的方法,這表明你實際上理解了這個概念,足以智能地使用它,而不僅僅是從引用中複製粘貼。

0

我想答案是,你不想在一個班級做兩件事。

CondimentDecorator做一件事:連接2種飲料。它確實應該命名爲「MixDecorator」

當您將調味品的常見方面分解爲編碼時,您需要創建另一個類,可以將其稱爲「NamedPricedCondiment」並將名稱和成本放在那裏。