聊聊设计模式——装饰者模式

目录

1.装饰者模式定义

2.优点

3.缺点

4.装饰者模式结构说明

5.工作流程

6.示例

7.代码练习

8.应用场景

9.本质

10.涉及的设计原则

11.相关的设计模式

12.开源框架中的应用


装饰者模式定义

        动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。装饰者模式通过将对象包装在装饰器对象中来实现这一目标,从而形成一条装饰器链。

优点
  • 允许动态地扩展对象的功能,避免了使用继承导致的类爆炸问题。
  • 可以通过组合不同的装饰器来构建灵活的对象结构。
  • 具体组件和装饰器都可以独立变化,符合单一职责原则。
缺点
  • 可能导致装饰器链变得复杂,不易理解。
  • 装饰器模式增加了许多小型对象,可能会导致性能损失。
装饰者模式结构说明
  1. Component(组件):定义了一个抽象接口,可以被具体组件和装饰器实现。这是装饰器模式中所有具体组件和装饰器的共同接口。
  2. ConcreteComponent(具体组件):实现了 Component 接口的具体组件类,是被装饰的对象,它可以被一个或多个装饰器包装。
  3. Decorator(装饰器):也实现了 Component 接口,但它通常包含一个对 Component 的引用,并且可以包装一个或多个其他装饰器或具体组件。
  4. ConcreteDecorator(具体装饰器):是装饰器模式中的具体装饰器类,它通过扩展装饰器类来添加额外的功能或行为。
工作流程
  1. 客户端通过 Component 接口与具体组件进行交互。
  2. 装饰器对象与具体组件实现相同的 Component 接口,这使得装饰器可以替代具体组件。
  3. 装饰器包装具体组件,可以添加额外的功能或行为。
  4. 客户端可以链式组合多个装饰器来构建复杂的对象结构。
示例

        装饰最简单的示例莫过于服饰了,一件衬衫上可以装饰胸针、袖扣,也可以加上口袋。

代码练习

1.创建抽象接口Clothes,提供一个sale()方法。

// 抽象接口 - 衣服
public interface Clothes {
    double sale();
}

2.创建装饰器Brooch、CuffLinks和Pocket,包含一个Clothes的引用

// 装饰器 - 胸针
public abstract class Brooch implements Clothes {
    protected Clothes clothes;
}
// 装饰器 - 袖扣
public abstract class CuffLinks implements Clothes {
    protected Clothes clothes;
}
// 装饰类 - 口袋
public abstract class Pocket implements Clothes {
    protected Clothes clothes;
}

3.创建被装饰的对象Shirt

// 具体组件类(被装饰对象) - 衬衫
public class Shirt implements Clothes {
    @Override
    public double sale() {
        return 50;
    }
}

4.创建具体装饰器BearBrooch、MonkeyCuffLinks和SquarePocket.

// 具体装饰类 - 小熊胸针
public class BearBrooch extends Brooch {

    public BearBrooch(Clothes clothes){
        this.clothes = clothes;
    }
    @Override
    public double sale() {
        return clothes.sale() + 5;
    }
}
// 具体装饰类 - 猴子袖扣
public class MonkeyCuffLinks extends CuffLinks {

    public MonkeyCuffLinks(Clothes clothes){
        this.clothes = clothes;
    }
    @Override
    public double sale() {
        return clothes.sale() + 10;
    }
}
// 具体装饰类 —— 方形口袋
public class SquarePocket extends Pocket {
    @Override
    public double sale() {
        return 0;
    }

    // 扩展功能
    public void takeSundries(String sundries){
        System.out.println("口袋里装了:" + sundries);
    }
}

客户端对衬衫进行装饰,扩展功能和行为:

public class DecoratorClient {
    public static void main(String[] args) {
        // 这是一件衬衫
        Clothes clothes = new Shirt();
        System.out.println("衬衫售价:" + clothes.sale());
        // 佩戴一枚小熊胸针
        clothes = new BearBrooch(clothes);
        System.out.println("小熊胸针衬衫售价:" + clothes.sale());
        // 佩戴猴子袖扣
        clothes = new MonkeyCuffLinks(clothes);
        System.out.println("猴子袖扣衬衫售价:" + clothes.sale());
        // 有口袋的衬衫
        clothes = new SquarePocket(clothes);
        // 口袋装了只笔
        ((SquarePocket) clothes).takeSundries("pen");
        System.out.printf("口袋衬衫的售价:" + clothes.sale());
    }
}
应用场景
  • 当需要在不修改现有代码的情况下动态地添加功能或行为时。
  • 当一个对象需要在运行时动态地添加或删除功能。
  • 当需要通过多个小型、独立的装饰器来构建复杂的对象。
本质

        动态地为对象添加功能。同时被装饰对象不感知这些功能的存在。这种方式允许在不修改现有代码的情况下扩展对象的行为,同时保持对象的单一职责原则。

涉及的设计原则
  • 开闭原则:可以在不修改现有代码的情况下扩展对象的功能。
  • 单一职责原则:每个类应该只有一个修改的理由,装饰器模式将功能的添加和具体组件的实现分开。
相关的设计模式
  • 装饰者模式通常与适配器模式工厂模式结合使用,以便创建和包装对象。
开源框架中的应用

        在Java中,I/O流的处理就是一个经典的装饰者模式的例子。例如,BufferedReader 和 BufferedWriter 都是装饰器,它们可以包装基本的 Reader 和 Writer,并添加缓冲功能,提高I/O性能。客户端可以根据需要链式组合多个装饰器来构建不同的I/O流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Elaine202391

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值