每天一种设计模式-装饰者模式

请添加图片描述

前言

写了两期设计模式的博客了,反过来自己读一读还是有一些生硬,对于没有基础的人来说可能阅读后没有理解,对于了解设计模式的人来说阅读后没有扩展,所以从本文开始决定试着寻找一种便于理解的模板。当然具体案例也是参考 《Head First 设计模式》文末也会总结遇到过或者看到过的案例。

需求

以星巴兹的咖啡为例,我们需要对星巴兹的饮料进行类设计

  1. 基本设计,我们抽象出一个 Beverage 基类 ,添加 descripition 属性,以及获取属性的方法和 cost () 计算价格的方法,目前整个星巴兹商店只有这四种饮料,类图如下:
    在这里插入图片描述
  2. 但是在购买咖啡时,有时需要添加各种调料,例如:奶、豆浆、糖、双份奶、摩卡、奶泡等等,我们再按照之前的设计,发现利用继承的方式,每一种咖啡新加一种调料都会新增一个子类,这简直是类爆炸,而且每次新增一种调料,我都需要增加多个组合的类,类数量是倍数递增,显然这么做是不好的。显然不符合可扩展性
    在这里插入图片描述
  3. 利用上述的方式显然不行的,那我们试试看从 Beverage 类下手,把调料设置成 饮料 的属性,每次 加入饮料我都利用 set 设置饮料属性,结算时利用 has 整理调料进行结算 类图如下:
    在这里插入图片描述
    嗯,这样确实解决了类爆炸的问题,而且利用 Beverage 的属性很容易计算出饮料的总价,这是客户来了说,我们新研发一种调料,并且因为牛奶涨价了,我们需要更改牛奶的价格,emmm 这样程序员只能去修改 Beverage 类,修改价格添加属性。。。。 显然,这违反了 开放-关闭原则,修改代码就意味着可能引起新的问题,并且需要重新从头测试。

装饰者模式

定义

在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 他是结构型设计模式

原则

  1. 多用组合,少用继承
  2. 开放-关闭原则:类应该对拓展开放,对修改关闭

使用

  • 装饰者和被装饰着对象具有相同的超类
  • 可以用一个或多个装饰着包装一个对象
  • 因为装饰者和被装饰着对象具有相同的超类,素以在任何需要原始对象(被包装的场合)场合,可以用装饰国的对象替换他
  • 装饰者可以在所委托被装饰者的行为之前或者之后,加上自己的行为,以达到特定的目的
  • 对象可以在被任何时候被装饰

重构

利用装饰者模式将星巴兹的饮料重构
在这里插入图片描述

  1. Beverage 详单与抽象的 Component(组成部分)
  2. HouseBlend 和 Espresso 代表原始类型
  3. CondimentDecorator 代表 装饰者
  4. Cappuccion 和 Mocha 代表装饰着具体的实现
    利用装饰者模式后,星巴兹的一种饮料组成就变成了如下
    在这里插入图片描述
    利用 cost方式很容易计算出 一整杯咖啡的价格了。

如果说现在 需要加上大杯、中杯的需求、只需要增加一个装饰者就可以了,而不需要改动原来的代码

装饰者模式的应用

Java I/O

在这里插入图片描述

  1. FilterInputStream 就是 Decorator 所有抽象装饰者的父类
  2. InputStream 就是Component 抽象组件,装饰者和被装饰者共同的父类
  3. ByteArrayInputStream 就是 ConcreteComponent 具体的组件对象,实现类 ,即被装饰者
  4. LinInputStream 就是 ConcreteDecorator 具体的装饰对象,实现具体要被装饰对象添加的功能。

我们想要io流中的大写字母全部转换成小写要怎么做呢

当时是增加新的装饰者了

public class LowerCaseInputStream extends FilterInputStream {
    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1 ? c:Character.toLowerCase(c));
    }
    
    /**
     * Creates a <code>FilterInputStream</code>
     * by assigning the  argument <code>in</code>
     * to the field <code>this.in</code> so as
     * to remember it for later use.
     *
     * @param in the underlying input stream, or <code>null</code> if
     *           this instance is to be created without an underlying stream.
     */
    protected LowerCaseInputStream(InputStream in) {
        super(in);
    }
}

spring 中的装饰者模式

  • org.springframework.cache.transaction 包下的 TransactionAwareCacheDecorator 类
    在这里插入图片描述

等等、等等

附言

代码和类图地址

感觉不错可以关注公众号呀 不定期更新知识分享

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1999

每人一点点,明天会更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值