设计模式(三)The_Decorator_Pattern(装饰者模式)

the Decorator Pattern

概述

装饰者模式实现的功能是在运行的时候使用object composition对象组合,从而达能在不改变代码的情况下给对象以新的功能。

问题提出

如果你想要设计一个饮品的类,那么你可能设计如下:

  • 一个抽象的Beverage
    • description,是一个实例变量,可以使String字符串,每个继承的子类都有设置
    • getDescription()
    • cost(); 是一个抽象的方法,每个子类都需要自己定义他们的价格。

这样在每次新添加一个款饮品时,就可以直接继承并且重写cost();

这看起来很好,但是对于维护来说确实一个噩梦。

比如如果牛奶的价格上涨,那么所有关于牛奶做原材料的饮品都需要价格上调。
而且对于咖啡来说,可以添加不同的调味品,那么对于不同调味品的组合,就需要产生不同的子类,导致子类太多!

那么是否可以在超类/父类中实例化这些调味品,然后继承跟踪这些呢?
新:
Beverage:

  • description
  • milk boolean型
  • soy
  • mocha
  • whip
  • getDescription()
  • cost() 现在cost方法不再是抽象的,这样能够计算通过调味品的状态来计算价格,子类也将会重写cost,但是他们会先调用super版本,来计算添加调配品后的基础价格。
  • hasMilk();
  • setMilk();
  • hasSoy();
  • 等等

原则:The Open-Closed Principle

Classes should be open for extension, but closed for modification;
类的设计应该对扩展开放,对修改关闭。

我们的目标是让类容易去在未修改代码的情况下去添加新的行为。一旦我们达成这样的设计,对于添加新的功能需求是平稳的并且可恢复的。

**注意:**小心选择需要扩展的代码区,到处使用Open-Closed Principle是没必要切浪费资源,增加代码复杂度,难于理解。

装饰模式

上边的解决方法仍然不是很好,可能产生类爆炸,不灵活的设计,或者在基类中添加一些不适用与所有子类的功能。

装饰者模式:对于咖啡的例子来说,我们在运行时动态添加调剂品,例如 :

  1. 创建一个DarkRoast子类
  2. 使用Mocha(摩卡)的类装饰一下
  3. 使用Whip(打泡)装饰
  4. 调用cost()函数,依靠代理(delegation)来添加调配品的价格

如何实现装饰?delegation是如何产生的?

按照包装的思想考虑:

  1. 开始于DarkRoash 对象
  2. 消费者想要摩卡,我们构建一个Mocha的对象,并且包装DarkRoash对象。
  3. Whip同理
    4.计算cost()时使用递归的思想。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPQZHhOj-1576402836142)(_v_images/20191209112130384_10807.png =652x)]

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ai43ULJI-1576402836144)(_v_images/20191209124139793_24032.png)]
有两个主要的基类,都是抽象类,分别是Beverage和CondimentDecorator, 其中CondimentDecorator又继承Beverage。
所有的饮品都继承Beverage, 所有的添加剂/调味品都继承CondimentDecorator.
在具体的CondimentDecorator的子类中,需要处理包装的功能。并且要保存Beverage变量。

//基类
public abstract class Beverage {
    String description = “Unknown Beverage”;
    public String getDescription() {
    return description;
    }
    public abstract double cost();
}

//装饰器基类,继承Beverage
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();    
}

/*一些子类*/
//特浓
public class Espresso extends Beverage {
    public Espresso() {
        description = “Espresso”;
    }
    public double cost() {
        return 1.99;
    }
}

public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = “House Blend Coffee”;
    }
    public double cost() {
        return .89;
    }
}

/*调味品*/
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());
        
        //DarkRoast
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription()
                + “ $” + beverage2.cost());
        
        //HouseBlend();
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);
        beverage3 = new Mocha(beverage3);
        beverage3 = new Whip(beverage3);
        System.out.println(beverage3.getDescription()
                + “ $” + beverage3.cost());
    }
}

简单来说,就是把能够组合的分离出来,但是都有共同的基类。
在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值