抽象装饰器类中的功能而不是装饰器

时间:2016-12-29 15:48:00

标签: java design-patterns decorator

我目前正在阅读这本书Head First Design Patterns,而在装饰器章节中有以下示例:

Example diagram

在书中, CondimentDecorator 类被描述为function one (a, cb) { } one('blah', function passedᅠintoᅠoneᅠㅣlineᅠ6 () { }) function two () { return function returnedᅠfromᅠtwoᅠㅣlineᅠ11 () { } } function three () { return { shoe: function asᅠpropertyᅠshoeᅠㅣlineᅠ17 () {} } } function four () { return function returnedᅠfromᅠfourᅠㅣlineᅠ22 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfourᅠᐳᅠㅣlineᅠ23 () { } } } function five () { return function returnedᅠfromᅠfiveᅠㅣlineᅠ30 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠㅣlineᅠ31 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠᐳᅠㅣlineᅠ32 () { foo('blue', function passedᅠintoᅠfooᅠㅣlineᅠ33 () { }) } } } } var six = function asᅠvarᅠsixᅠㅣlineᅠ42 () { } var seven = function asᅠvarᅠsevenᅠㅣlineᅠ47 (err, cb) { return function returnedᅠfromᅠᐸᅠasᅠvarᅠsevenᅠᐳᅠㅣlineᅠ49 () { cb(function passedᅠintoᅠcbᅠㅣlineᅠ50 () { }) } } var o = {}; o.eight = function asᅠpropertyᅠeightᅠㅣlineᅠ58 (cb) { } o.eight(function passedᅠintoᅠoːeightᅠㅣlineᅠ61 () { }) o.eight.nine = function asᅠpropertyᅠnineᅠㅣlineᅠ63 () {} o.eight.nine(function passedᅠintoᅠeightːnineᅠㅣlineᅠ64 () { }) var o2; o2 = function asᅠvarᅠo2ᅠㅣlineᅠ68 () { } ;(function IIFEᅠㅣlineᅠ71 () {}()) !function IIFEᅠㅣlineᅠ73 () { }() function toodeep () { return function returnedᅠfromᅠtoodeepᅠㅣlineᅠ78 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠㅣlineᅠ79 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠㅣlineᅠ80 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ82 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ83 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ84 () { return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ86 () { return function () { return function () { return function () { } } } } } } } } } } } 。这是代码示例:

abstract decorator

所以基本上内部只是一个抽象方法,它强制所有子类覆盖 Beverage 类的public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } 方法。

以下是 Mocha 类的代码示例getDescription()

decorator

其他装饰器( Whip 类, Soy 类......)具有完全相同的代码,但硬编码的成本编号(.20)和名称(& #34;,Mocha")。

然后我们通过将前一个对象传递给新的装饰器来使用这个装饰器模式。

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

我的问题是,为什么不简单地将重复的功能从装饰器移到抽象装饰器?以下是我重构示例的方法。

抽象装饰者:

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

现在,对于我创建的每个新装饰器,我都被迫通过超类构造函数的构造函数提供前一个饮料对象,我需要覆盖只返回特定装饰器的唯一值的方法。

这段代码好吗?或者,如果我在抽象装饰器中有功能,它是否完全改变了装饰器模式的要点?

2 个答案:

答案 0 :(得分:1)

这段代码很好。教科书经常(?)在他们的例子中提供不完美的代码,因此他们可以专注于特定的概念(在这种情况下 - 装饰器),而不是引起对其他细节的关注。您找到了改进本书代码的方法这一事实表明,您实际上已经理解了这个概念,可以智能地使用它,而不仅仅是从参考文献中复制粘贴。

答案 1 :(得分:0)

我认为答案是你不想在一堂课中做两件事。

CondimentDecorator做一件事:连接2份饮料。它确实应该命名为" MixDecorator"

当您将调味品的常见方面分解为编码时,您需要创建另一个类,可以将其称为" NamedPricedCondiment"并将名称和费用放在那里。