装饰者模式

需求

咖啡店,客户可能会叫一种饮料,并且指定某些调料加入进去,比如深焙咖啡,用摩卡,奶泡,牛奶作为调料,计算出总价

饮料类,被装饰者

/**
 * 饮料父类
 */
public abstract class Beverage
{
    /**
     * 描述饮料的字段
     */
    protected String description = "Unknown Berverage";

    public String getDescription()
    {
        return description;
    }

    /**
     * 计算价钱的方法,必须在子类中实现
     */
    public abstract double cost();
}

/**
 * 暗烤咖啡
 */
public class DarkRoast extends Beverage
{
    public DarkRoast()
    {
        description = "暗烤咖啡 DarkRoast"; // 描述此饮料
    }

    /**
     * 返回此饮料的价钱
     */
    @Override
    public double cost()
    {
        return .99;
    }
}

调料类,装饰者

/**
 * 调料类,也就是装饰者
 * 
 * 为了让 装饰者 能够替代 被装饰者 ,因此 装饰者 继承 被装饰者
 */
public abstract class Condiment extends Beverage
{
    /**
     * 所有的装饰者类,都必须重新实现此方法,因为必须有不同的名称
     */
    @Override
    public abstract String getDescription();
}

/**
 * 摩卡调料
 */
public class Mocha extends Condiment
{
    private Beverage beverage; // 用来记住 被装饰者 ,也就是此调料要加在哪个饮料上

    /**
     * 想办法把被装饰者记录在变量中
     */
    public Mocha(Beverage beverage)
    {
        this.beverage = beverage;
    }

    /**
     * 把被装饰者和装饰者的名称组合起来,比如:混合咖啡,摩卡
     */
    @Override
    public String getDescription()
    {
        return beverage.getDescription() + ", 摩卡调料 Mocha";
    }

    /**
     * Mocha自身的价钱+饮料的价钱
     */
    @Override
    public double cost()
    {
        return 0.20 + beverage.cost();
    }
}

/**
 * 豆奶调料
 */
public class Soy extends Condiment
{
    private Beverage beverage;

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

    @Override
    public String getDescription()
    {
        return beverage.getDescription() + ", 豆奶调料 Soy";
    }

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

测试

// 点一杯饮料
Beverage beverage2 = new DarkRoast();
// 用调料去装饰饮料
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
// 算出总价钱
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());

疑问

  • 以上全用了继承,这里是利用继承达到类型匹配的目的,并不是获得行为。方便更有弹性的混合匹配
  • 每当需要新的调料,甚至是新的饮料,都可以新增并方便的加入
  • 并非一定要用接口,如果抽象类用的好好的,并且已经满足需求,就不用再去修改他
  • 会导致有很多的小类

Java 中应用到装饰者模式的地方

Java I/O

设计原则 5

类应该对扩展开放,对修改关闭,在不修改现有代码的情况下,就搭配新的行为

装饰者模式定义:

动态的将责任附加到对象上,对于扩展的话,比继承更有弹性。

你可能感兴趣的:(装饰者模式)