一篇文章带你搞懂装饰者模式

1、装饰者模式

  装饰者模式是指在无需改变原有类及类的继承关系的情况下,动态扩建一个类的功能。通过装饰者来包裹真实的对象,并动态地向对象添加或者撤销功能。动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。
在这里插入图片描述

  • Component:抽象组件,定义业务需要实现的抽象方法
  • ConcreteComponent:具体组件,继承(或实现)Component,定义主体对象
  • Decorator:装饰者(可以为具体实现类或抽象类),实现Component接口并聚合其对象,用于给具体组件增加或减少功能
  • ConcreteDecorator:具体装饰者(具体实现类),抽象类的子类,负责向组件中装饰(扩充)新的职责

2、Demo

  举一个我们日常生活中的例子,我们去买饮料 =》奶茶,奶茶一开始只有原味奶茶,往奶茶里添加各种配料如珍珠、波霸、红豆等,价格均发生改变。在程序中,我们可以通过继承来实现,但顾客的需求是同时加好几种配料,那我们的继承类就得好几十个,这样的做法明显是不合理的。但是通过装饰者模式,我们就可以轻松实现:把饮料定义为抽象类(或接口),原味奶茶为饮料的具体实现类,再添加一个装饰器装饰原味奶茶的描述和价格,然后把珍珠、红豆等配料作为具体的装饰器实现类,且所有的装饰器都聚合了一个Drink对象。

  • Component
package com.lin.decorator;

public abstract class Drink {

    public abstract String desc();

    public abstract int price();
}
  • ConcreteComponent
package com.lin.decorator;

public class YuanWeiMilkTea extends Drink {
    @Override
    public String desc() {
        return "原味奶茶";
    }

    @Override
    public int price() {
        return 10;
    }
}
  • Decorator
package com.lin.decorator;

public class MilkTea extends Drink {

    private Drink drink;

    public MilkTea(Drink drink) {
        this.drink = drink;
    }

    @Override
    public String desc() {
        return drink.desc();
    }

    @Override
    public int price() {
        return drink.price();
    }
}
  • ConcreteDecorator
package com.lin.decorator;

public class ZenZhuMilkTea extends MilkTea {
    public ZenZhuMilkTea(Drink drink) {
        super(drink);
    }

    @Override
    public String desc() {
        return super.desc() + " + 珍珠";
    }

    @Override
    public int price() {
        return super.price() + 2;
    }
}
package com.lin.decorator;

public class BoBaMilkTea extends MilkTea {
    public BoBaMilkTea(Drink drink) {
        super(drink);
    }

    @Override
    public String desc() {
        return super.desc() + " + 波霸";
    }

    @Override
    public int price() {
        return super.price() + 3;
    }
}
package com.lin.decorator;

public class RedBeanMilkTea extends MilkTea {
    public RedBeanMilkTea(Drink drink) {
        super(drink);
    }

    @Override
    public String desc() {
        return super.desc() + " + 红豆";
    }

    @Override
    public int price() {
        return super.price() + 10;
    }
}
  • 测试
public static void main(String[] args) {
    //原味奶茶
    Drink tea = new YuanWeiMilkTea();
    MilkTea milkTea = new MilkTea(tea);
    System.out.println(milkTea.desc() + ":" + milkTea.price());
    //加珍珠
    milkTea = new ZenZhuMilkTea(milkTea);
    System.out.println(milkTea.desc() + ":" + milkTea.price());
    //加波霸
    milkTea = new BoBaMilkTea(milkTea);
    System.out.println(milkTea.desc() + ":" + milkTea.price());
    //加红豆
    milkTea = new RedBeanMilkTea(milkTea);
    System.out.println(milkTea.desc() + ":" + milkTea.price());
}
原味奶茶:10
原味奶茶 + 珍珠:12
原味奶茶 + 珍珠 + 波霸:15
原味奶茶 + 珍珠 + 波霸 + 红豆:25

3、装饰器模式在Java中的应用

3.1、节点流和处理流

  我们都知道Java中IO流可以分为节点流和处理流,看节点流和处理流的定义是不是很像上面的在奶茶上添加配料

  • 节点流:直接从数据源或目的地读写数据
  • 处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更强大的读写功能
3.2、UML
  • InputStream:类似上面的Drink,是一个抽象类
  • FileInputStream:类似上面的YuanWeiMilk,是Drink的实现类
  • FilterInputStream:类似上面Decorator,是装饰器
  • BufferedInputStream、DataInputStream…:类似上面Decorator的实现类,就是Drink的各种配料
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值