23种设计模式,装饰器模式的概念优缺点以及JAVA代码举例

简介: 【4月更文挑战第5天】装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。

概念

装饰器模式涉及四个角色:

  • 组件(Component):定义一个对象接口,可以给这些对象动态地添加职责。
  • 具体组件(Concrete Component):定义了一个具体的对象,也可以给这个对象添加一些职责。
  • 装饰(Decorator):持有一个组件(Component)对象的实例,并定义了与组件接口一致的接口。
  • 具体装饰(Concrete Decorator):负责给组件添加额外的职责。

优点

  1. 增加对象的职责:装饰器模式提供了一种灵活的替代方案来扩展对象的功能,比继承更加灵活。
  2. 动态地添加功能:装饰器模式允许用户动态地给一个对象添加额外的职责。添加的职责也容易撤销。
  3. 扩展系统功能:可以使用多个不同的装饰器对同一个对象进行装饰,实现不同的效果。

缺点

  1. 会导致系统产生很多小对象:每个装饰器都是一个对象,过多使用装饰器会造成程序中小对象的数量大增。
  2. 复杂性增加:装饰器模式会增加系统的复杂性,多层装饰比较复杂。
  3. 维护困难:大量使用装饰器,维护时需要特别注意装饰链的配置,可能会引起错乱。

Java代码示例

考虑一个简单的咖啡店系统,咖啡是一种饮料,顾客可以选择添加不同的调料(如牛奶、摩卡、豆浆等)。

首先,定义组件接口:

java复制代码

public interface Beverage {
    String getDescription();
    double cost();
}

具体组件实现:

java复制代码

public class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

public class HouseBlend implements Beverage {
    @Override
    public String getDescription() {
        return "House Blend Coffee";
    }

    @Override
    public double cost() {
        return 0.89;
    }
}

装饰器实现:

java复制代码

public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
    public abstract String getDescription();
}

具体装饰实现:

java复制代码

public class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    @Override
    public double cost() {
        return .20 + beverage.cost();
    }
}

public class Soy extends CondimentDecorator {
    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Soy";
    }

    @Override
    public double cost() {
        return .15 + beverage.cost();
    }
}

使用示例:

java复制代码

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        Beverage beverage2 = new HouseBlend();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Soy(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    }
}

在这个例子中,EspressoHouseBlend是具体的饮料,MochaSoy是装饰者,它们通过包装一个Beverage对象并在其基础上添加额外的功能(即调料)来工作。

相关文章
|
23天前
|
设计模式 XML Java
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
27 0
|
10天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
22 1
|
10天前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
27 0
[Java]23种设计模式
|
26天前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
26天前
|
设计模式 Java
Java设计模式
Java设计模式
25 0
|
29天前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
26 0
|
29天前
|
设计模式 Java
Java设计模式之桥接模式
这篇文章介绍了Java设计模式中的桥接模式,包括桥接模式的目的、实现方式,并通过具体代码示例展示了如何分离抽象与实现,使得两者可以独立变化。
40 0
|
8天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
79 38
|
5天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
7天前
|
安全 Java
在 Java 中使用实现 Runnable 接口的方式创建线程
【10月更文挑战第22天】通过以上内容的介绍,相信你已经对在 Java 中如何使用实现 Runnable 接口的方式创建线程有了更深入的了解。在实际应用中,需要根据具体的需求和场景,合理选择线程创建方式,并注意线程安全、同步、通信等相关问题,以确保程序的正确性和稳定性。