设计模式-装饰模式

文章目录

一、简介

装饰模式是一种结构型设计模式,它允许动态地向对象添加额外的功能。

二、基本概念

  1. 装饰模式定义:在不改变原有对象结构的情况下,通过对其进行包装拓展,以达到增强功能的目的。
  2. 装饰器角色:负责给组件对象附加额外的功能,实现了与组件具有相同接口的装饰器类。
  3. 组件角色:拥有核心功能的原始对象。
  4. 抽象组件角色:定义了组件对象的接口,可以是抽象类或接口。
  5. 具体组件角色:实现了抽象组件角色的具体对象。

三、装饰模式的结构和实现

类图解析:

java 复制代码
// 抽象组件角色
public interface Component {
    void operation();
}

// 具体组件角色
public class ConcreteComponent implements Component {
    public void operation() {
        // 实现核心功能
        System.out.println("这是具体组件角色的核心功能");
    }
}

// 装饰器角色
public abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

// 具体装饰器角色
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    public void operation() {
        // 添加额外功能代码
        System.out.println("具体装饰器角色:"+"执行核心组件的功能前111");
        super.operation();
        // 添加额外功能代码
        System.out.println("具体装饰器角色:"+"执行核心组件的功能后2222");
    }
}
  1. 客户端代码示例:
java 复制代码
Component component = new ConcreteComponent(); // 创建具体组件对象
component.operation(); // 调用核心功能

Component decoratedComponent = new ConcreteDecorator(component); // 使用具体装饰器装饰组件
decoratedComponent.operation(); // 调用增强功能

装饰器的实现方式

继承实现:

具体装饰器继承装饰器抽象类,通过重写父类方法实现功能拓展
  1. 继承实现方式:
java 复制代码
// 抽象组件角色
interface Component {
    void operation();
}

// 具体组件角色
class ConcreteComponent implements Component {
    public void operation() {
        // 执行核心功能
        System.out.println("执行核心功能");
    }
}

// 抽象装饰器角色
abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

// 具体装饰器角色
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        // 添加额外的功能代码
        System.out.println("添加额外的功能代码A");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        // 添加额外的功能代码
        System.out.println("添加额外的功能代码B");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        // 创建具体组件对象
        Component component = new ConcreteComponent();

        // 创建具体装饰器对象,并包装组件对象
        Component decoratorA = new ConcreteDecoratorA(component);
        Component decoratorB = new ConcreteDecoratorB(decoratorA);

        // 调用装饰器的操作方法,实现功能的拓展
        decoratorB.operation();
    }
}

组合实现:

具体装饰器持有装饰器抽象类的实例,通过调用实例方法实现功能拓展。

  1. 组合实现方式:
java 复制代码
// 抽象组件角色
interface Component {
    void operation();
}

// 具体组件角色
class ConcreteComponent implements Component {
    public void operation() {
        // 执行核心功能
        System.out.println("执行核心功能");
    }
}

// 装饰器角色
class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

// 具体装饰器角色
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        // 添加额外的功能代码
        System.out.println("添加额外的功能代码A");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        // 添加额外的功能代码
        System.out.println("添加额外的功能代码B");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        // 创建具体组件对象
        Component component = new ConcreteComponent();

        // 创建具体装饰器对象,并包装组件对象
        Component decoratorA = new ConcreteDecoratorA(component);
        Component decoratorB = new ConcreteDecoratorB(decoratorA);

        // 调用装饰器的操作方法,实现功能的拓展
        decoratorB.operation();
    }
}

这两个示例中,都有一个抽象的组件角色(Component),一个具体的组件角色(ConcreteComponent),以及几个具体的装饰器角色(ConcreteDecorator)。具体装饰器角色在构造函数中接收一个组件对象,并在自身的 operation() 方法中调用组件对象的 operation() 方法,并添加额外的功能代码。

在使用示例中,我们创建了具体组件对象和具体装饰器对象,并将它们进行组合,最后调用装饰器的 operation() 方法来实现功能的拓展。

继承和组合对比

在装饰器模式中,继承实现和组合实现是两种常见的方式。它们在实现装饰器功能时略有不同:

继承实现:

  • 优点:
    • 简单直接:通过继承抽象装饰器类,具体装饰器可以直接重写方法并添加额外功能。
    • 可复用性高:可以轻松地创建多个具体装饰器,并进行组合拓展。
  • 缺点:
    • 类爆炸:每个具体装饰器都需要创建一个新的类,当装饰器数量增多时,类的数量也会大量增加。
    • 静态结构:类的组合和功能拓展是在编译时静态决定的,无法动态地改变组合方式。

组合实现:

  • 优点:
    • 灵活组合:具体装饰器持有抽象装饰器对象,可以在运行时动态地组合不同的装饰器对象,实现不同的功能拓展组合。
    • 类结构简单:相对于继承实现,不需要创建过多的具体装饰器类,类结构相对简单。
  • 缺点:
    • 代码复杂度较高:需要在具体装饰器中额外处理抽象装饰器对象的方法调用。可能需要在抽象装饰器中定义一些默认实现,以避免空指针异常。

根据具体需求和设计考虑,可以选择适合的实现方式。继承实现适用于静态且数量有限的装饰器组合,而组合实现适用于动态和灵活的装饰器组合。两种实现方式都能实现装饰器模式的基本功能,只是在代码结构和使用方式上略有差异。

四、装饰模式的应用场景

  1. 动态添加功能:当需要在不修改现有代码的情况下,动态地给对象添加新功能时,装饰模式可以很好地满足这一需求。
  2. 避免子类爆炸:利用装饰模式,可以避免通过创建大量子类来实现各种功能组合的问题。
  3. 透明性 vs. 安全性:装饰模式中的装饰器和组件具有相同的接口,使得对于客户端而言,无需关心具体是使用了原始组件还是装饰器对象,实现了透明性。

五、与其他模式的关系

  1. 装饰模式 vs. 适配器模式:装饰模式侧重于给对象动态添加功能,而适配器模式则是为了让不兼容的类能够协同工作。
  2. 装饰模式 vs. 组合模式:装饰模式和组合模式都采用了递归组合的思想,但装饰模式着重于给对象添加功能,而组合模式着重于构建对象的树形结构。
  3. 装饰模式 vs. 桥接模式:桥接模式将抽象部分和实现部分解耦,而装饰模式则是在不改变对象结构的基础上,拓展其功能。

六、总结

装饰模式通过包装对象实现功能的动态拓展,使得系统具有更高的灵活性和可扩展性。它应用广泛,在动态添加功能、避免子类爆炸等场景都很有价值。同时,要注意使用装饰模式时,保持透明性和安全性的平衡,确保装饰器和组件具有一致的接口。

相关推荐
monkey_meng15 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss23 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
我救我自己23 分钟前
UE5运行时创建slate窗口
java·服务器·ue5
2401_8532757344 分钟前
ArrayList 源码分析
java·开发语言
爪哇学长1 小时前
SQL 注入详解:原理、危害与防范措施
xml·java·数据库·sql·oracle
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
她说彩礼65万1 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc
MoFe11 小时前
【.net core】【sqlsugar】字符串拼接+内容去重
java·开发语言·.netcore
陈随易1 小时前
农村程序员-关于小孩教育的思考
前端·后端·程序员
_江南一点雨1 小时前
SpringBoot 3.3.5 试用CRaC,启动速度提升3到10倍
java·spring boot·后端