Java设计模式之装饰器模式(Decorator)笔记

目录

什么叫做装饰器模式

装饰器模式的作用

装饰器模式的特征

装饰器模式的应用场景

装饰器模式的实现

定义组件

定义具体组件 

定义装饰器 

进行测试

总结


什么叫做装饰器模式

        装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你在不修改现有对象的前提下,动态地添加功能或责任到对象上。这种模式通过创建一个包装器类来实现,在这个包装器类中包含了原始类的实例,并且可以在不改变原始类的接口的情况下,增加额外的行为或功能。

        装饰器模式遵循了面向对象设计中的开放封闭原则单一职责原则,可以通过添加新的装饰器类来引入新的功能,而无需修改已有的组件类。同时每个装饰器只负责一个特定的功能。

装饰器模式的作用

        避免类爆炸:通过装饰器模式,可以避免创建大量子类以覆盖各种组合可能性,从而防止类的爆炸性增长。相比之下,继承方式的扩展可能会导致类的数量迅速增加,难以维护。

        分离关注点:装饰器模式使得每个装饰器类专注于一个特定的责任或功能,这有助于代码的可维护性,因为每个装饰器类都只关心它自己的功能,而不需要了解整个对象的复杂性。

        灵活性和组合性:你可以通过组合多个装饰器来创建不同的功能组合,这使得你可以按需组装对象的行为,以满足具体需求。这种方式比静态继承更加灵活,因为你可以在运行时决定对象的行为。

装饰器模式的特征

        组件(Component):这是一个抽象类或接口,定义了装饰器和具体组件的共同接口,它可以是具体组件或装饰器的父类。

        具体组件(Concrete Component):这是实现了组件接口的具体类,它是被装饰的原始对象。

        装饰器(Decorator):这是一个抽象类,它继承自组件接口,并包含一个对组件的引用,通常以构造函数的方式传递给装饰器。装饰器可以添加额外的行为或修改组件的行为。

        具体装饰器(Concrete Decorator):这是继承自装饰器的具体类,它实现了装饰器的方法并可以添加额外的功能。

装饰器模式的应用场景

        图形用户界面(GUI)框架:在GUI开发中,装饰器模式可用于添加各种UI组件的装饰,比如按钮、文本框等,以增加额外的功能,如边框、滚动条、提示等。

        文件流处理:在文件操作中,可以使用装饰器模式来包装文件流,以添加不同的功能,比如缓冲、加密、压缩等,而无需修改文件流的接口。

        日志记录:装饰器模式可用于日志记录,通过装饰器可以添加额外的信息,如时间戳、日志级别等,以改进日志的内容和格式。

        身份验证和授权:在网络应用中,可以使用装饰器模式来添加身份验证和授权功能,以控制用户对资源的访问。例如,可以创建一个身份验证装饰器,该装饰器验证用户的身份,然后根据权限控制访问。

装饰器模式的实现

        现在我们通过一个奶茶店的例子来了解一下装饰器模式的实现。

定义组件

        定义了奶茶的基本行为,包括成本(cost)和描述(getDescription)方法。在装饰器模式中,它是所有具体组件(ConcreteComponent)和装饰器(Decorator)的共同接口

// 奶茶接口
public interface MilkTea {
    double cost();
    String getDescription();
}

 

定义具体组件 

        定义实现了 MilkTea 接口的具体奶茶类。它是装饰器模式中的基础组件,它定义了最基本的奶茶,包括其价格和描述。

// 基础奶茶类
public class SimpleMilkTea implements MilkTea {
    @Override
    public double cost() {
        return 5.0; // 基础奶茶的价格
    }

    @Override
    public String getDescription() {
        return "简单奶茶";
    }
}

 

定义装饰器 

        定义装饰器类,实现了 MilkTea 接口。

// 珍珠装饰器
public class PearlDecorator implements MilkTea {
    private final MilkTea decoratedMilkTea;

    public PearlDecorator(MilkTea decoratedMilkTea) {
        this.decoratedMilkTea = decoratedMilkTea;
    }

    @Override
    public double cost() {
        return decoratedMilkTea.cost() + 1.5; // 添加珍珠的价格
    }

    @Override
    public String getDescription() {
        return decoratedMilkTea.getDescription() + " + 珍珠";
    }
}
// 糖装饰器
public class SugarDecorator implements MilkTea {
    private final MilkTea decoratedMilkTea;

    public SugarDecorator(MilkTea decoratedMilkTea) {
        this.decoratedMilkTea = decoratedMilkTea;
    }

    @Override
    public double cost() {
        return decoratedMilkTea.cost() + 1.0; // 添加糖的价格
    }

    @Override
    public String getDescription() {
        return decoratedMilkTea.getDescription() + " + 糖";
    }
}

 

进行测试

public class Test {
    public static void main(String[] args) {
        // 创建一个基础奶茶
        MilkTea basicMilkTea = new SimpleMilkTea();
        System.out.println("奶茶描述: " + basicMilkTea.getDescription());
        System.out.println("价格: $" + basicMilkTea.cost());

        // 添加珍珠
        MilkTea milkTeaWithPearl = new PearlDecorator(basicMilkTea);
        System.out.println("奶茶描述: " + milkTeaWithPearl.getDescription());
        System.out.println("价格: $" + milkTeaWithPearl.cost());

        // 再添加糖
        MilkTea milkTeaWithPearlAndSugar = new SugarDecorator(milkTeaWithPearl);
        System.out.println("奶茶描述: " + milkTeaWithPearlAndSugar.getDescription());
        System.out.println("价格: $" + milkTeaWithPearlAndSugar.cost());
    }
}

        测试结果:

 

总结

优点:

  1. 灵活性和扩展性: 装饰器模式允许你在运行时动态地添加或删除对象的功能,而无需修改其源代码。这提供了很大的灵活性,使系统更容易扩展。
  2. 遵循开闭原则: 通过使用装饰器,你可以遵循开闭原则,即对扩展开放,对修改关闭。你可以添加新的装饰器来引入新的功能,而不会影响到现有的代码。
  3. 适用于组合: 装饰器模式允许你将对象按照各种方式组合,创建出复杂的对象结构,而不需要大量的子类。这减少了类的数量,使系统更加清晰。
  4. 单一职责原则: 每个装饰器只关注一个特定的功能,这有助于保持类的单一职责原则。这使得代码更容易维护和测试。

缺点:

  1. 复杂性增加: 装饰器模式可能会导致类的数量增加,特别是在有多个装饰器的情况下,这可能会增加代码的复杂性和理解难度。
  2. 容易出错: 如果不正确地组合装饰器,可能会导致运行时错误。选择和组合装饰器需要谨慎,以确保功能不会冲突或重复。
  3. 不适合所有情况: 装饰器模式适用于需要动态添加功能的情况,但对于那些需要静态功能组合的情况,可能不是最佳选择。在某些情况下,使用继承可能更为简单和合适。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ikwil

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

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

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

打赏作者

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

抵扣说明:

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

余额充值