Functionality inside abstract decorator class instead of decorators
我目前正在阅读《Head First Design Patterns》一书,在"Decorator"一章中有以下示例:
在书中,conditionmentDecorator类被描述为一个
1 2 3 | public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } |
因此,基本上内部只是一个抽象方法,它强制所有子类从饮料类重写
这里是一个mocha类的代码示例,作为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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(); } } |
其他装修商(鞭子类,大豆类…)有完全相同的代码,除了硬编码的成本数字(.20)和名称(",摩卡")。
然后,我们通过将前一个对象传递给新的装饰器来使用这个装饰器模式。
1 2 3 4 | Beverage beverage = new DarkRoast(); beverage = new Mocha(beverage); beverage = new Mocha(beverage); beverage = new Whip(beverage); |
我的问题是,为什么不简单地将复制的功能从装饰器移到抽象装饰器?下面是我如何重构示例。
抽象装饰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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(); } |
装饰代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Mocha extends CondimentDecorator { public Mocha(Beverage beverage) { super(beverage); } @Override public String getAdditionName() { return"Mocha"; } @Override public double getAdditionCost() { return 0.20; } } |
现在,对于我创建的每个新的装饰器,我都必须通过超类构造函数的构造函数提供以前的饮料对象,并且我需要重写仅返回特定装饰器的唯一值的方法。
这个代码可以吗?或者,如果我在抽象装饰器中具有功能,它是否完全改变了装饰器模式的要点?
这个代码很好。经常阅读课本(?)在他们的示例中呈现不太完美的代码,这样他们就可以专注于一个特定的概念(在本例中是装饰师),而不必关注其他细节。事实上,你找到了一种改进这本书代码的方法,这表明你实际上已经很好地理解了这个概念,能够智能地使用它,而不仅仅是从引用中复制粘贴。
我认为答案是你不想在一节课上做两件事。
当你把调料的共同方面分解成代码时,你需要创建另一个类,可以称之为"命名调料",并将名称和成本放在里面。