Head First Design Patterns 阅读笔记之三: Decorator Pattern

欢迎来到 Starbuzz Coffee

星巴克作为一家扩展最快的咖啡店,它们现在需要更新饮料订购系统以便满足现在庞大的需求。这个订购系统的第一版如下:
first edition

显然这对于日后的维护来说,完全是个噩梦。这里需要提到一个设计原则(Open-Closed Principles):

类应当对扩展开放,对修改封闭
Classes should be open for extension, but closed for modication.

我们的目标是让类易于扩展以便包含新的行为,同时不去修改现存的源代码。但是并不是在每个部分都要采用这一原则,如果到处滥用,反而会导致代码复杂。一般在代码最重要并且会变化的地方采用这一原则。


使用 Decorator Pattern

如果一个顾客需要 Dark Roast,加 Mocha 和 Whip。我们这么做:

  • Take a DarkRoast object
  • Decorate it with a Mocha object
  • Decorate it with a Whip object
  • Call the cost() method and rely on delegation to add on the condiment costs

但是这里的 decorate 怎么做?我们可以把它看做封装器(wrapper)。

Decorator

下面给一个正式的定义:

The Decorator Pattern attaches additional reponsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

下面给一个图像实例:
图像实例

而在之前的情境下,可以画出如下框架:
Starbuzz beverge

public abstract class Beverage
{
    String description = "Unknown Beverage";

    public String getDescription() 
    { 
        return description;
    }

    public abstract double cost();
}

// 与此类似实现咖啡类 HouseBlend,Espresso,Decaf 类
public class DarkRoast extends Beverage
{
    public DarkRoast() 
    { 
        description = "Dark Roast Coffee";
    }

    public double cost()
    {
        return 0.99;
    }
}
public abstract class CondimentDecorator extends Beverage
{
    public abstract String getDescription();
}

// 与此类似实现调料类 SteamMilk,Soy,Whip 类
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();
    }
}
// 测试
public class StarbuzzCoffee
{
    public static void main(String[] args)
    {
        Beverage beverage = new Espresso(); 
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2); 
        beverage2 = new Mocha(beverage2); 
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());

        Beverage beverage3 = new HouseBlend();
         beverage3 = new Soy(beverage3); 
         beverage3 = new Mocha(beverage3); 
         beverage3 = new Whip(beverage3);
        System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
    }
}

现实中的 Decorators:Java I/O,Java I/O 大量使用了 Decorator Pattern。但是 Java I/O 也指出了 Decorator Pattern的一个问题:使用这个模式会有很多小类,这会让使用者感到恐慌。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值