小侃设计模式(八)-装饰者模式

本文解析装饰者模式的概念,通过奶茶制作案例展示其实现过程,并探讨其在Java IO类中的应用。了解装饰者模式的优点与局限,以及如何在实际项目中灵活运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

装饰者模式是一种结构性设计模式,它能够动态地将新功能附加到对象上,却又不改变对象,在对象功能扩展方面,比继承更富有弹性,且符合开闭原则。这种模式创建了一个类,用来包装原有的类,在保证原来类的功能前提下,增加了额外的功能。本文将分析装饰者模式的概念及使用。

2.概念及使用

2.1 类图

装饰者类图如下:
在这里插入图片描述
上述类图包含了装饰着四个核心的部分:抽象组件(Component)、被装饰者(ConcreteComponent)、装饰者组件(Decorator)、具体装饰类(ConcreteDecorator),具体解释如下:

(1)抽象组件(Component):抽象出一个接口,规范需要准备接受附加责任的对象;
(2)被装饰者(ConcreteComponent):需要装饰的具体对象;
(3)装饰者组件(Decorator):装饰者基类,用于持有组件对象的实例引用,装饰具体的组件对象;
(4)具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能。

2.2 案例

顾客在奶茶店里点奶茶,奶茶有不同的品种:原味奶茶、黑糖珍珠奶茶、芒果耶奶奶茶等,店员也可以根据客户需要制作不同的奶茶。这里就可以用装饰者模式来对奶茶对象进行加工,生成顾客最终需要的奶茶。

在这里插入图片描述
编码如下:

//定义抽象组件(奶茶)
public interface MilkyTea {

    String makeTea();

    Double calCost();
}

//定义被装饰者(这里以原味奶茶为基础)
public class PureMilkyTea implements MilkyTea {

    private Double cost;

    public Double getCost() {
        return cost;
    }

    public void setCost(Double cost) {
        this.cost = cost;
    }

    public String makeTea() {
        System.out.println("原味奶茶基础材料");
        return "pureMilkyTea";
    }

    public Double calCost() {
        System.out.println("原味奶茶基础价格为10元");
        setCost(10.0);
        return this.cost;
    }
}

//定义装饰者组件
public abstract class Decorator implements MilkyTea{

    public MilkyTea milkyTea;

    public Decorator(MilkyTea milkyTea) {
        this.milkyTea = milkyTea;
    }

    abstract void addMilk();

    abstract void addMongo();

    abstract void addPearl();

}

//定义具体装饰类:芒果椰奶奶茶装饰类(MongoCocoTea)和黑糖珍珠奶茶装饰类(PearlyTea)
public class MongoCocoTea extends Decorator {

    public MongoCocoTea(MilkyTea milkyTea) {
        super(milkyTea);
    }

    @Override
    void addMilk() {
        System.out.println("添加椰奶。。。");
    }

    @Override
    void addMongo() {
        System.out.println("添加芒果。。。");
    }

    @Override
    void addPearl() {
        System.out.println("添加珍珠。。。");
    }


    @Override
    public String makeTea() {
        System.out.println("制作芒果椰奶奶茶。。。");
        milkyTea.makeTea();
        addMilk();
        addMongo();
        System.out.println("芒果椰奶奶茶制作完成");
        return "MongoCocoTea";
    }

    @Override
    public Double calCost() {
        //原味奶茶价格
        Double price = milkyTea.calCost();
        //加椰奶价格
        price += 10;
        //加芒果价格
        price += 5;
        return price;
    }
}

public class PearlyTea extends Decorator {

    public PearlyTea(MilkyTea milkyTea) {
        super(milkyTea);
    }

    @Override
    void addMilk() {
        System.out.println("添加牛奶。。。");
    }

    @Override
    void addMongo() {
        System.out.println("添加芒果。。。");
    }

    @Override
    void addPearl() {
        System.out.println("添加黑糖珍珠。。。");
    }


    @Override
    public String makeTea() {
        System.out.println("制作黑糖珍珠奶奶茶。。。");
        milkyTea.makeTea();
        addMilk();
        addPearl();
        System.out.println("黑糖珍珠奶茶制作完成");
        return "PearlyTea";
    }

    @Override
    public Double calCost() {
        //原味奶茶价格
        Double price = milkyTea.calCost();
        //加牛奶价格
        price += 5;
        //加黑糖珍珠价格
        price += 8;
        return price;
    }
}

//测试代码如下
public class Test {

    public static void main(String[] args) {

        PureMilkyTea pureMilkyTea = new PureMilkyTea();
        PearlyTea pearlyTea = new PearlyTea(pureMilkyTea);
        pearlyTea.makeTea();
        System.out.println("黑糖珍珠奶茶价格为" + pearlyTea.calCost());

        System.out.println("-------------------------------");

        MongoCocoTea mongoCocoTea = new MongoCocoTea(pureMilkyTea);
        mongoCocoTea.makeTea();
        System.out.println("芒果耶耶奶茶价格为:" + mongoCocoTea.calCost());
    }
}

运行结果如下:
在这里插入图片描述

2.3 装饰者模式在jdk源码中的应用

在JAVA的IO类中,体现了装饰者模式的应用,具体类图如下:
在这里插入图片描述

public abstract class InputStream implements Closeable{}是一个抽象组件(Component);
public class FilterInputStream extends InputStream {}是一个装饰者类;
protected volatile InputStream in;这是具体的被装饰对象
public class DataInputStream extends FilterInputStream implements DataInput {} 是FilterInputStream的一个子类,也继承了被装饰对象InputStream。

2.4 装饰者优缺点

2.4.1 优点

1.装饰者模式提供了比继承更加符合开闭原则,具有更好的灵活性;因为继承是在静态期间确立关系,而装饰者是在运行时动态添加对象的功能;
2.解耦,通过增加子类方式来修改对象创建行为,这种通过增加而不是修改类的方式,是面向对象设计所推崇的。

2.4.2 缺点

1.会在系统中产生较多的类,造成系统臃肿;
2.使用难度较高,对设计人员抽象能力要求较高。

3.小结

1.装饰者模式一种结构性模式,它的作用是避免使用继承的方式来扩展对象的功能,而是通过动态添加的方式来增加功能;
2.装饰模式在使用时,需要根据场景进行抽象,选出关键的Component、ConcreteComponent、Decorator、ConcreteDecorator。

4.参考文献

1.《设计模式-可复用面向对象软件的基础》-Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides
2.《可复用物联网Web3D框架的设计与实现》-程亮(知网)
3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式
4.《大话设计模式》-程杰著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值