装饰者模式(Decorator Pattern)——给爱用继承的人一个全新的设计眼界

概述

     装饰者模式(Decorator Pattern),别名(Warpper)。 动态的将责任附加到对象上。若要扩展功能,装饰者提供比继承更有弹性的替代方案。

     装饰者模式从属的大类是结构型模式(该大类下的设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式)。

     涉及的设计原则:

     1. 开放–关闭原则类(应该对扩展开放,对修改关闭)

     2. 多用组合,少用继承

类图

这里写图片描述

需要注意的东西

     由上面类图可知,装饰者模式,由Component(抽象组件)、ConcreteComponent(具体组件)、Decorator(抽象装饰类)、ConcreteDecorator(具体装饰类)组成。其主要功能从上面类图可以看出。在此需要注意几点:

  1. 上述中Components和Decorator均可以是接口也可以是抽象类。
  2. 装饰者和被装饰者需要实现相同的接口或者抽象类。即装饰者和被装饰者对象拥有相同的超类。
  3. 可以用一个或多个装饰者包装一个对象。
  4. 装饰者模式的用意是包吃接口并增加对象的职责。
  5. 一张图看懂装饰者模式流程。

这里写图片描述

应用场景

     星巴克咖啡对其出售的咖啡的一种销售策略的价格做一下统计、这样当顾客点了他们想要的搭配的时候我们就可以知道最后的价格是多少。

     假设有四种咖啡:HouseBlend、DarkRoaat、Decaf、Espresso。

     同样有四种配料可以选择:Milk、Mocha、Soy、Mocha。

     这四种咖啡有不同的价格、同样四种搭配也有不同的价格。当我们把这个单子拿给顾客的时候、顾客可以任意点一种咖啡、可以任意搭配。我们的目的是要统计每种搭配的价格、那我们要怎么来实现呢?当我们要添加一个或多个新的品种或者配料的时候,又如何有效的解决这个问题呢?这就是装饰者模式的解决的问题。

代码实现

这里为了简化代码,只采用两种咖啡HouseBlend、Espresso,两种配料Mocha、Mocha,这样的搭配。

package decorator;

/**
 * <p>ClassName      Beverage
 * <p>Description    超类
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 0:51
 */
public abstract class Beverage {
    String description = "unknow Beverage";

    public String getDescription() {
        return description;
    }

    /**
     * 计算花费
     *
     * @return
     */
    public abstract Double cost();
}
package decorator;

/**
 * <p>ClassName      CondimentDecorator
 * <p>Description   配料抽象类
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 0:55
 */
public abstract class CondimentDecorator extends Beverage {
    /**
     * 所有的配料装饰者都需要重写getDescription
     */
    public abstract String getDescription();
}
package decorator;

/**
 * <p>ClassName      Espresso
 * <p>Description    一种饮品(具体的组件)
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:01
 */
public class Espresso extends Beverage {
    public Espresso() {
        description = "Espresso";
    }

    public Double cost() {
        return 1.99;
    }
}
package decorator;

/**
 * <p>ClassName      HouseBlend
 * <p>Description    另外一种饮品(具体的组件)
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:04
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "HouseBlend";
    }

    public Double cost() {
        return 0.89;
    }
}
package decorator;

/**
 * <p>ClassName      Mocha
 * <p>Description    具体装饰者
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:05
 */
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 0.2 + beverage.cost();
    }
}
package decorator;

/**
 * <p>ClassName      Whip
 * <p>Description    具体装饰者
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:12
 */
public class Whip extends CondimentDecorator {
    Beverage beverage; //被装饰者

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

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

    public Double cost() {
        return 66.66 + beverage.cost();
    }
}
package decorator;

/**
 * <p>ClassName      TestDecorator
 * <p>Description    测试类
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:09
 */
public class TestDecorator {
    public static void main(String[] args) {
        /**
         * 一杯Espresso,不加配料
         */
        Beverage beverage = new Espresso();
        System.out.println( beverage.getDescription() + " $" + beverage.cost() );

        /**
         * 一杯Houseblend,加Mocha,Whip
         */
        Beverage beverage1 = new HouseBlend();
        beverage1 = new Mocha( beverage1 );
        beverage1 = new Whip( beverage1 );
        System.out.println( beverage1.getDescription() + " $" + beverage1.cost() );
    }
}
运行结果

这里写图片描述

总结

     又get一种新的pattern。

    装饰者模式比继承更加灵活机动,但是不要忘记了装饰者模式的别名warpper,如果过度使用,多层warpper,会使程序变得很复杂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值