设计模式探索:装饰器模式

news2024/11/13 12:14:35

1. 装饰器模式定义

装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,允许向一个对象动态添加行为。在不改变类的接口的情况下,装饰器模式在原始类上增加额外的职责,并且支持多个装饰器嵌套使用。
在这里插入图片描述

装饰器模式代码示例

抽象构件类

/**
 * 抽象构件类
 * 该类声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。
 */
public abstract class Component {
    // 抽象方法,由具体构件和装饰类实现
    public abstract void operation();
}

具体构件类

/**
 * 具体构件类
 * 该类实现了抽象构件类的业务方法,是被装饰的对象。
 */
public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent: 基础功能实现");
    }
}

抽象装饰类

/**
 * 抽象装饰类
 * 该类是装饰者模式的核心,继承了抽象构件类,并持有一个抽象构件类型的对象引用。
 */
public abstract class Decorator extends Component {
    // 维持一个对抽象构件对象的引用
    protected Component component;

    // 注入一个抽象构件类型的对象
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        // 调用原有业务方法
        component.operation();
    }
}

具体装饰类

/**
 * 具体装饰类
 * 该类是装饰者模式的具体实现类,向构件添加新的职责。
 */
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); // 调用原有业务方法
        addedBehavior(); // 调用新增业务方法
    }

    // 新增业务方法
    public void addedBehavior() {
        System.out.println("ConcreteDecorator: 新增业务功能");
    }
}

客户端使用示例

public class Client {
    public static void main(String[] args) {
        // 创建具体构件对象
        Component component = new ConcreteComponent();
        
        // 使用装饰类进行装饰
        Component decoratedComponent = new ConcreteDecorator(component);
        
        // 调用装饰后的方法
        decoratedComponent.operation();
    }
}

输出结果

ConcreteComponent: 基础功能实现
ConcreteDecorator: 新增业务功能

解析

  • 抽象构件类(Component):声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。
  • 具体构件类(ConcreteComponent):实现了抽象构件类的业务方法,是被装饰的对象。
  • 抽象装饰类(Decorator):继承了抽象构件类,持有一个抽象构件类型的对象引用,并实现了业务方法,通过调用引用对象的方法实现对业务方法的调用。
  • 具体装饰类(ConcreteDecorator):继承了抽象装饰类,实现了新增的业务方法。

通过这种设计模式,装饰器可以在不修改原始类代码的情况下,为原始类添加新的功能,并且支持多个装饰器的嵌套使用,从而灵活地增强原始类的功能。

2. 装饰器模式与代理模式的区别

代理模式(Proxy Pattern)

代理模式也是一种结构型设计模式,为其他对象提供一个代理,以控制对这个对象的访问。代理模式的主要目的是控制访问,而非增强功能。
在这里插入图片描述

  1. 目的意图不同

    • 装饰器模式:主要是为了增强目标类的功能。
    • 代理模式:主要是为了控制对目标类的访问。
  2. 使用差别

    • 装饰器模式:装饰器对目标对象没有控制权,目标对象的方法一定会被执行。
    • 代理模式:代理对象对目标对象有控制权,可以选择执行或不执行目标对象的方法。
  3. 对于客户端的关注点

    • 装饰器模式:客户端更关心的是对目标对象进行增强后的功能。
    • 代理模式:客户端更关心的是被代理对象的功能。

3. 装饰器模式在实际开发中的应用

**需求:**有多个装饰时是怎么保证后面的装饰,在前面装饰的基础上装饰的。比如字符,需要加密+压缩。怎么能让压缩,在加密的基础上压缩?

3.1 创建字符组件接口

public interface StringComponent {
    String transform(String str);
}

3.2 实现字符组件

// 字符组件
public class StringEncryptor implements StringComponent {
    @Override
    public String transform(String str) {
        // base64编码
        return Base64.getEncoder().encodeToString(str.getBytes());
    }
}

3.3 字符加密装饰器

public class StringEncryptorDecorator implements StringComponent {
    private StringComponent component;

    public StringEncryptorDecorator(StringComponent component) {
        this.component = component;
    }

    @Override
    public String transform(String str) {
        String encrypted = component.transform(str); // 调用前面一个装饰器或组件的方法
        // 这里演示一个简单的压缩方法,将字符串压缩成一行
        return encrypted.replaceAll("\\s+", "");
    }
}

3.4 字符压缩的装饰器

public class StringCompressorDecorator implements StringComponent {
    private StringComponent component;

    public StringCompressorDecorator(StringComponent component) {
        this.component = component;
    }

    @Override
    public String transform(String str) {
        String compressed = component.transform(str); // 调用前面一个装饰器或组件的方法
        // 这里演示一个简单的压缩方法,将字符串压缩成一行
        return compressed.replaceAll("\\s+", "");
    }
}

3.5 客户端

public class Client {
    public static void main(String[] args) {
        StringComponent component = new StringEncryptor(); // 创建字符加密组件
        component = new StringEncryptorDecorator(component); // 用字符加密装饰器装饰它
        component = new StringCompressorDecorator(component); // 用字符压缩装饰器再次装饰它

        String original = "Hello, world!"; // 原始字符串
        String transformed = component.transform(original); // 转换后的字符串
        System.out.println(transformed);
    }
}

输出结果为:SGVsbG8sIHdvcmxkIQ==,这是对原始字符串进行加密和压缩后的结果。可以看到,压缩操作在加密操作的基础上进行了。

4. 装饰器模式总结

装饰器模式概述

装饰器模式是一种结构型设计模式,旨在动态地给对象添加额外的职责。

优点:

  1. 灵活性: 装饰器模式允许在运行时通过添加装饰器来扩展对象的功能,比静态继承更加灵活。
  2. 可扩展性: 可以对一个对象进行多次装饰,以实现不同的行为或功能。
  3. 低耦合度: 装饰器模式允许开发者在不修改对象本身的情况下增加新功能。
  4. 开闭原则: 符合开闭原则,即对扩展开放,对修改封闭。

缺点:

  1. 对象数量多: 装饰器模式可能会产生许多小的装饰器对象,增加系统的复杂性。
  2. 错误机会多: 由于装饰器数量可能很多,增加了出错的机会。
  3. 性能问题: 装饰器模式可能会引入额外的性能开销,尤其是在多层装饰的情况下。

适用场景:

  1. 动态添加职责: 当需要动态地给对象添加职责,而不是通过继承增加子类。
  2. 透明性: 需要保持对象的接口不变,即装饰前后对象的接口完全一致。
  3. 不支持继承: 在不支持或不便于使用继承来扩展功能的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双色球 | python

1. 玩法规则 “双色球”每注投注号码由 6 个红色球号码和 1 个蓝色球号码组成。红色球号码从 1—33 中选择,蓝色球号码从 1—16 中选择。 球的数字匹配数量和颜色决定了是否中奖。 2. 需求 生成本期双色球中奖号码。(注意:1.生成的红球随机有…

Vuforia AR篇(八)— AR塔防上篇

目录 前言一、设置Vuforia AR环境1. 添加AR Camera2. 设置目标图像 二、创建塔防游戏基础1. 导入素材2. 搭建场景3. 创建敌人4. 创建脚本 前言 在增强现实(AR)技术快速发展的今天,Vuforia作为一个强大的AR开发平台,为开发者提供了…

Docker-compse的应用

1 docker-compose # 使用了docker 面临一个比较大的问题,如果一个djagno项目,使用mysql,redis,不要一次性把所有服务都放到一个容器中,每个服务一个容器,批量的管理多个容器,比较难以操作&…

昇思25天学习打卡营第1天|小试牛刀

这里写自昇思25天学习打卡营第1天|小试牛刀定义目录标题 昇思25天学习打卡营第1天学习了初学入门之基本介绍。了解了昇思MindSpore和华为昇腾AI全栈。训练营中的教程丰富,有初学入门、应用实践和量子计算等。学习打卡营是很好的提升自己的机会。 昇腾计算&#xff…

前端图表库G2快速上手

文档地址&#xff1a; https://g2-v3.antv.vision/zh/docs/manual/getting-started/ https://g2.antv.antgroup.com/ 安装&#xff1a; pnpm i antv/g2在vue3中使用&#xff1a; <script setup> import {Chart} from antv/g2; import {onMounted} from "vue"…

生成多个ssh访问不同git

如果&#xff0c;你的git代码仓库&#xff0c;比如说腾讯云coding&#xff0c;通过ssh秘钥访问&#xff0c;一直用的好好的&#xff0c;有一天&#xff0c;你又增加一个aliyun云效的代码仓库&#xff0c;又配置了aliyun云效的秘钥并且&#xff0c;根据aliyun云效的官方文档上传…

【持续集成_03课_Linux部署Sonar+Gogs+Jenkins】

一、通过虚拟机搭建Linux环境-CnetOS 1、安装virtualbox&#xff0c;和Vmware是一样的&#xff0c;只是box更轻量级 1&#xff09;需要注意内存选择&#xff0c;4G 2、启动完成后&#xff0c;需要获取服务器IP地址 命令 ip add 服务器IP地址 通过本地的工具&#xff0c;进…

后端——全局异常处理

一、老办法try-catch 当我们执行一些错误操作导致程序报错时&#xff0c;程序会捕捉到异常报错&#xff0c;这个异常会存在一个Exception对象里 那我们在spring boot工程开发时&#xff0c;当我们执行一个sql查询时报错了&#xff0c;那就会从最底层的Mapper层捕捉到Exceptio…

三相感应电机的建模仿真(3)基于ABC相坐标系Level2 S-Fun以及定子串不对称电抗起动过程仿真分析

1. 概述 2. 三相感应电动机状态方程式 3. 基于Level2 S-Function的仿真模型建立 4. 动态分析实例 5. 总结 6. 参考文献 1. 概述 三相感应电机自然坐标系下的数学模型是一组周期性变系数微分方程(其电感矩阵是转子位置角的函数,转子位置角随时间按正弦规律变化),将其用…

工作手机监管系统销售防飞单保护企业资源

在竞争激烈的市场环境中&#xff0c;企业的每一笔交易都承载着发展的希望与未来的蓝图。然而&#xff0c;飞单现象如同暗流涌动&#xff0c;悄然侵蚀着企业的利润根基&#xff0c;威胁着团队的凝聚力与客户的信任。为了构建更加稳固的业务防线&#xff0c;我们隆重介绍——百川…

Instruct-GS2GS:通过用户指令编辑 GS 三维场景

Paper: Instruct-GS2GS: Editing 3D Gaussian Splats with Instructions Introduction: https://instruct-gs2gs.github.io/ Code: https://github.com/cvachha/instruct-gs2gs Instruct-GS2GS 复用了 Instruct-NeRF2NeRF 1 的架构&#xff0c;将基于 NeRF 的三维场景编辑方法迁…

gpt-4o看图说话-根据图片回答问题

问题&#xff1a;中国的人口老龄化究竟有多严重&#xff1f; 代码下实现如下&#xff1a;&#xff08;直接调用openai的chat接口&#xff09; import os import base64 import requests def encode_image(image_path): """ 对图片文件进行 Base64 编码 输入…

“郑商企航”暑期社会实践赴美丽美艳直播基地开展调研

马常旭文化传媒网讯&#xff08;记者张明辉报道&#xff09;导读&#xff1a;2024 年 7 月 3 日&#xff0c;商学院暑期社会实践团“郑商企航”在河南省郑州市新密市岳村镇美丽美艳直播基地&#xff0c;展开了一场意义非凡的考察活动&#xff0c;团队成员深度调研了直播基地的产…

昇思MindSpore学习总结十二 —— ShuffleNet图像分类

当前案例不支持在GPU设备上静态图模式运行&#xff0c;其他模式运行皆支持。 1、ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达…

读书笔记-Java并发编程的艺术-第4章(Java并发编程基础)-第3节(线程间通信)

文章目录 4.3 线程间通信4.3.1 volatile和synchronized 关键字4.3.2 等待/通知机制4.3.3 等待/通知的经典范式4.3.4 管道输入 / 输出流4.3.5 Thread.join()的使用4.3.6 ThreadLocal的使用 4.3 线程间通信 线程开始运行&#xff0c;拥有自己的栈空间&#xff0c;就如同一个脚本…

简单的找到自己需要的flutter ui 模板

简单的找到自己需要的flutter ui 模板 网站 https://flutterawesome.com/ 简介 我原本以为会很难用 实际上不错 很简单 打开后界面类似于,右上角可以搜索 点击view github 相当简单 很oks

卷积神经网络——LeNet——FashionMNIST

目录 一、整体结构二、model.py三、model_train.py四、model_test.py GitHub地址 一、整体结构 二、model.py import torch from torch import nn from torchsummary import summaryclass LeNet(nn.Module):def __init__(self):super(LeNet,self).__init__()self.c1 nn.Conv…

Java--instanceof和类型转换

1.如图&#xff0c;Object&#xff0c;Person&#xff0c;Teacher&#xff0c;Student四类的关系已经写出来了&#xff0c;由于实例化的是Student类&#xff0c;因此&#xff0c;与Student类存在关系的类在使用instanceof时都会输出True&#xff0c;而无关的都会输出False&…

Vatee万腾平台:创新科技,驱动未来

在科技日新月异的今天&#xff0c;每一个创新的火花都可能成为推动社会进步的重要力量。Vatee万腾平台&#xff0c;作为科技创新领域的佼佼者&#xff0c;正以其卓越的技术实力、前瞻性的战略眼光和不懈的探索精神&#xff0c;驱动着未来的车轮滚滚向前。 Vatee万腾平台深知&am…

STM32实战篇:按键控制LED

按键控制LED 功能要求 有两个按键&#xff0c;分别控制两个LED灯。当按键按下后&#xff0c;灯的亮暗状态改变。实物如下图所示&#xff1a; 由图可知&#xff0c;按键一端直接接地&#xff0c;故另一端所对应IO引脚的输入模式应该为上拉输入模式。 实现代码 #include "…