浅谈装饰模式

news2025/5/11 12:34:22

一、前言

        hello大家好,本次打算简单聊一下装饰者模式,其实写有关设计模式的内容还是蛮有挑战性的,首先呢就是小永哥实力有限担心说不明白,其次设计模式是为了解决某些问题场景,在当前技术生态圈如此完善的情况下,能遇到使用设计模式的时候其实还是蛮少见的,而且我一直认为解决方案本身没有好坏之分,只有经过取舍适合当前的才是最好的。任何事物都是双刃剑,包括设计模式,在没有适合场景的情况下强行使用反而会造成过度设计,这样就不好了。

        不过呢前几天小永哥确实遇到了一个小场景能用一下装饰者模式,不过作为演示呢我就不完整复刻那些复杂的代码了,咱来点简易的类比一下,尽量以少的代码能说明白。

二、业务场景

        当时的业务场景是一个Excel导入功能,我们都知道导入时,需要读取逐行读取Excel数据,每行数据又要对应列的数据读取出来赋值给实体类对象,每一行就是一个实体类对象,最后将这些实体类对象设置到提前声明好的list集合中并调用批量保存完成导入,简易导入请看下述代码。

package com.relation;

import com.alibaba.fastjson2.JSON;
import org.apache.poi.ss.usermodel.*;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 20:20
 */
public class ImportTest {
    @Test
    public void test() throws IOException {
        ArrayList<Map<String,Object>> mapList = new ArrayList<>();
        // 导入的源文件
        String path = "E:\\test\\demo.xlsx";
        // 工作薄对象
        Workbook workbook = WorkbookFactory.create(new FileInputStream(path));
        // 工作表 sheet
        Sheet sheet = workbook.getSheetAt(0);
        // 行
        int rows = sheet.getPhysicalNumberOfRows();
        DataFormatter dataFormatter = new DataFormatter();
        // 行的头信息,第一行,可以不处理
        for (int i = 1; i < rows; i++) {
            Row row = sheet.getRow(i);
            Map<String,Object> demoData = new HashMap<>();
            // 第一个单元格,因为是序号,可以不要
            // 从第二个单元格开始获取名称
            String name = dataFormatter.formatCellValue(row.getCell(1));
            demoData.put("name",name);
            // 第三个单元格获取编号
            String code = dataFormatter.formatCellValue(row.getCell(2));
            demoData.put("code",code);
            // 把组装好的 student对象,存入集合
            mapList.add(demoData);
        }
        System.out.println(JSON.toJSONString(mapList));
    }
}

         以上就是一个简易的excel上传代码,运行测试类也能从excel中获取到数据,一个很正常和普通的小需求,想来以各位老铁的本事,这些都不叫事。下面有请我们T哥给我上点强度。

三、来自T哥的折磨

        T哥:一般找我来都没啥好事,不过能给你填点堵我还是很乐意的。

        小白:T哥你客气了,有事您吩咐,没有困难我制造困难也给你整明白儿的。

        T哥:好了,废话少说,为了减少用户手输的错误率,你看能不能给表格内容去空格呀,防止用户不小心在前后多输空格然后又检查不出来。

        小白:那太简单了,你就瞧好吧......

        3.1、去空格需求的实现。

        很简单嘛,给设置值的位置调用一下String自带的trim()方法不就好了,很轻松呀。

        3.2、来自T哥的新需求。

        T哥:这么快就实现了,不愧是专业的java开发人员,那个什么,客户要求除去空格之外,需要将每个数据都加上一个前缀AAA。这个能实现吧。

        小白:好吧,也不是什么问题。

我们可以看到小白很快又搞定了,但是小白陷入了沉思。

        小白:不对呀,为什么我每次都要改所有单元格设置的位置呢?我得想办法写个方法把这些集中起来,这样我只需要在第一次修改的时候改动位置稍微多一点,以后每次我修改集中起来的代码就好了。说干就干。

        

package com.relation;

import com.alibaba.fastjson2.JSON;
import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 20:20
 */
public class ImportTest {
    @Test
    public void test() throws IOException {
        // 将Excel文件导入到数据库中
        ArrayList<Map<String,Object>> mapList = new ArrayList<>();
        // 导入的源文件
        String path = "E:\\test\\demo.xlsx";
        // 工作薄对象
        Workbook workbook = WorkbookFactory.create(new FileInputStream(path));
        // 工作表 sheet
        Sheet sheet = workbook.getSheetAt(0);
        // 行
        int rows = sheet.getPhysicalNumberOfRows();
        DataFormatter dataFormatter = new DataFormatter();
        // 行的头信息,第一行,可以不处理
        for (int i = 1; i < rows; i++) {
            Row row = sheet.getRow(i);
            Map<String,Object> demoData = new HashMap<>();
            // 第一个单元格,因为是序号,可以不要
            // 从第二个单元格开始获取名称
            String name = dataFormatter.formatCellValue(row.getCell(1));
            demoData.put("name",getStr(name));
            // 第三个单元格获取编号
            String code = dataFormatter.formatCellValue(row.getCell(2));
            demoData.put("code",getStr(code));
            // 把组装好的 student对象,存入集合
            mapList.add(demoData);
        }
        System.out.println(JSON.toJSONString(mapList));
    }

    private String getStr(String data){
        if(StringUtils.isEmpty(data)){
            return data;
        }
        return "AAA"+data.trim();
    }
}

        小白抽取了一个方法,专门用来处理表格内容,好像比之前要好很多了。

        T哥:你进步了,已经开始能自查并完善自己的代码了......

        小白:当然了,每次都改那么多地方,我累,能少改干嘛要多改呢?

        T哥:那既然你这么说,那你抽取getStr方法之后,不还是得在第一次修改的时候,逐个找到每个获取表格的位置去替换为使用getStr方法吗?

        小白:还好吧,只有两处而已,有必要再折腾吗?

        T哥:没错,现在确实是只有名称和编码两个属性,那万一有几十个属性呢?你也要一个个去修改吗?不是你自己说能少写一行代码就不多写一行吗?

        小白:那好吧,我再想想办法,毕竟我是一个面向对象工程师......

        3.3、面向对象方式改造
package com.relation;

import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 21:47
 */
public class DataFormatterExpand extends DataFormatter {

    @Override
    public String formatCellValue(Cell cell) {
        String cellValue = super.formatCellValue(cell);
        if(StringUtils.isEmpty(cellValue)){
            return cellValue;
        }
        return "AAA"+cellValue.trim();
    }
}
package com.relation;

import com.alibaba.fastjson2.JSON;
import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 20:20
 */
public class ImportTest {
    @Test
    public void test() throws IOException {
        // 将Excel文件导入到数据库中
        ArrayList<Map<String,Object>> mapList = new ArrayList<>();
        // 导入的源文件
        String path = "E:\\test\\demo.xlsx";
        // 工作薄对象
        Workbook workbook = WorkbookFactory.create(new FileInputStream(path));
        // 工作表 sheet
        Sheet sheet = workbook.getSheetAt(0);
        // 行
        int rows = sheet.getPhysicalNumberOfRows();
        DataFormatterExpand dataFormatter = new DataFormatterExpand();
        // 行的头信息,第一行,可以不处理
        for (int i = 1; i < rows; i++) {
            Row row = sheet.getRow(i);
            Map<String,Object> demoData = new HashMap<>();
            // 第一个单元格,因为是序号,可以不要
            // 从第二个单元格开始获取名称
            String name = dataFormatter.formatCellValue(row.getCell(1));
            demoData.put("name",name);
            // 第三个单元格获取编号
            String code = dataFormatter.formatCellValue(row.getCell(2));
            demoData.put("code",name);
            // 把组装好的 student对象,存入集合
            mapList.add(demoData);
        }
        System.out.println(JSON.toJSONString(mapList));
    }
}

 

        我们可以看到,小白扩展了一个类并继承了DataFormatter并重写了formatCellValue方法,先调用父类的formatCellValue,然后再对获取的值进行统一扩展完成任务。

        T哥:很好,一个非常标准的OO设计。

        小白:当然了,我可是一个专业的OO程序员。

        T哥:其实做到这一步已经设计的很不错了,代码改动也少,变化的代码也抽取出去了,那还有可以改进的地方吗?

        小白:我不是很明白,现在不是很完美了吗?为什么还要改进?

        T哥:如果针对此功能需求到此为止,那你的设计可以说完美,但是如果后续还有变化呢?你还能优雅保持你的扩展性吗?

        小白:我想是可以的。

        T哥:好的,那咱们继续,

        3.4、T哥的BUFF叠加

        T哥:来新需求了,我们需要再加上BBB后缀。

        小白:这简单,我继续修改一下。

        T哥:新需求来了,要求把AAA前缀去掉......

        小白:T哥,你怕不是玩死我吧?

        T哥:你说的什么话,不是你让我来给你提需求吗?

        小白:我*******

        T哥:我*******

        然后T哥和小白打起来了.........

        小永哥:小白你先放手,这事儿哥帮你办了,你先消消气。

        3.5、小永哥的改造
package com.relation.expand;

import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 21:47
 */
public class DataFormatterTrimExpand extends DataFormatter {

    private DataFormatter dataFormatter;

    public void setDataFormatter(DataFormatter dataFormatter) {
        this.dataFormatter = dataFormatter;
    }

    @Override
    public String formatCellValue(Cell cell) {
        String cellValue = dataFormatter.formatCellValue(cell);
        if(StringUtils.isEmpty(cellValue)){
            return cellValue;
        }
        return cellValue.trim();
    }
}

        

package com.relation.expand;

import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 21:47
 */
public class DataFormatterPrefixExpand extends DataFormatter {

    private DataFormatter dataFormatter;

    public void setDataFormatter(DataFormatter dataFormatter) {
        this.dataFormatter = dataFormatter;
    }

    @Override
    public String formatCellValue(Cell cell) {
        String cellValue = dataFormatter.formatCellValue(cell);
        if(StringUtils.isEmpty(cellValue)){
            return cellValue;
        }
        return "AAA"+cellValue;
    }
}

package com.relation.expand;

import com.relation.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 21:47
 */
public class DataFormatterSuffixExpand extends DataFormatter {

    private DataFormatter dataFormatter;

    public void setDataFormatter(DataFormatter dataFormatter) {
        this.dataFormatter = dataFormatter;
    }

    @Override
    public String formatCellValue(Cell cell) {
        String cellValue = dataFormatter.formatCellValue(cell);
        if(StringUtils.isEmpty(cellValue)){
            return cellValue;
        }
        return cellValue+"BBB";
    }
}
package com.relation.expand;

import org.apache.poi.ss.usermodel.DataFormatter;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 22:27
 */
public class DataFormatterFactory {

    public static DataFormatter createDataFormatter(){
        DataFormatter dataFormatter = new DataFormatter();
        //创建去空格扩展类
        DataFormatterTrimExpand dataFormatterTrimExpand = new DataFormatterTrimExpand();
        //创建加前缀扩展类
        DataFormatterPrefixExpand dataFormatterPrefixExpand = new DataFormatterPrefixExpand();
        //创建加后缀扩展类
        DataFormatterSuffixExpand dataFormatterSuffixExpand = new DataFormatterSuffixExpand();
        //按需求进行组合
        //将原生DataFormatter设置到去空格扩展类来达到去空格功能
        dataFormatterTrimExpand.setDataFormatter(dataFormatter);
        //将去空格扩展类设置到加前缀扩展类,来给去空格后的值加前缀
        dataFormatterPrefixExpand.setDataFormatter(dataFormatterTrimExpand);
        //将加前缀扩展类设置到加后缀扩展类,给加完前缀值在加上后缀
        dataFormatterSuffixExpand.setDataFormatter(dataFormatterPrefixExpand);
        return dataFormatterSuffixExpand;
    }
}
package com.relation;

import com.alibaba.fastjson2.JSON;
import com.relation.expand.DataFormatterFactory;
import com.relation.expand.DataFormatterTrimExpand;
import org.apache.poi.ss.usermodel.*;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huhy
 * @version 1.0
 * @Description:
 * @ClassName Date:2025/5/10 20:20
 */
public class ImportTest {
    @Test
    public void test() throws IOException {
        // 将Excel文件导入到数据库中
        ArrayList<Map<String,Object>> mapList = new ArrayList<>();
        // 导入的源文件
        String path = "E:\\test\\demo.xlsx";
        // 工作薄对象
        Workbook workbook = WorkbookFactory.create(new FileInputStream(path));
        // 工作表 sheet
        Sheet sheet = workbook.getSheetAt(0);
        // 行
        int rows = sheet.getPhysicalNumberOfRows();
        DataFormatter dataFormatter = DataFormatterFactory.createDataFormatter();
        // 行的头信息,第一行,可以不处理
        for (int i = 1; i < rows; i++) {
            Row row = sheet.getRow(i);
            Map<String,Object> demoData = new HashMap<>();
            // 第一个单元格,因为是序号,可以不要
            // 从第二个单元格开始获取名称
            String name = dataFormatter.formatCellValue(row.getCell(1));
            demoData.put("name",name);
            // 第三个单元格获取编号
            String code = dataFormatter.formatCellValue(row.getCell(2));
            demoData.put("code",code);
            // 把组装好的 student对象,存入集合
            mapList.add(demoData);
        }
        System.out.println(JSON.toJSONString(mapList));
    }
}

我们可以看到,经过小永哥的改造,前缀和后缀都加上了,但是好像代码量多了很多。

        小白:永哥,你这是什么名堂,为啥你改造完以后代码量反而更多了呢?

        小永哥:你说的对,初期确实代码量比你的OO设计要多了不少,待我给你好好介绍一下。

        3.6、代码解析

        1)、如下图所示,我们为每一种扩展都创建了对应的实现类。

        2)、我们改造了扩展类,我们加了一个DataFormatter类型的成员变量,我们不再调用父类的方法,而是调用成员变量的方法。

        3)、这样做的好处是,成员变量可以是原生的类,也可是我们的扩展类,这样的话,我们就可以按照需求灵活对扩展类进行组合。

        4)、我们创建了一个简易的工厂DataFormatterFactory来生成DataFormatter,将我们组合的逻辑封装在工厂类的createDataFormatter方法中,从此刻开始,我们已经将所有变化的东西,从我们的主业务逻辑中抽取了出来。

        5)、经过一系列的改造,我们的代码可扩展性和可维护性已经大大的提高了,需求变化时,如果我们已经有对应的扩展类,则直接进行组合即可,如果没有对应的扩展类,我们可以创建新的扩展类,并进行新的组合。

        T哥:小永哥有两下子哈,小白你能总结一下你小永哥这么做符合哪些原则吗?

        小白:首先,小永哥对每一种扩展创建对应的实现类,满足了单一职责。对于新的扩展,创建新的实现类,而不对业务代码进行修改,符合开闭原则,但好像对工厂类有改动,好像又没有很完美的符合开闭原则。

        T哥:你说的很对,开闭原则是对修改关闭,对新增开放以大大减少对已有稳定代码的改动,以减少需求变化对系统的影响,但是要完全做到开闭原则很难,我们在开发过程中或多或少都会涉及到对原有代码的改动,这个是不可避免的,小永哥可以说将代码改动控制在很小范围之内了,如果出现问题,排查范围也会小很多。

        小永哥:不好意思,我插一句哈,在扩展类的改造中,我使用了组合模式,利用组合模式松耦合的特性来提升系统的弹性,小白这一点你要牢记,有时候有一个比是一个要更好,说的更直白一点,就是组合模式要比继承的灵活性更强。

        小白:永哥,我记住了。

        3.7、总结

        经过了一系列的改造,我们已经将代码改造好了,特别是最后一次改造,运用的就是经典的装饰模式。通过自由组合的方式对原始的类进行层层装饰,从而达到我们的目的。

四、结语

        又耗费了不少脑细胞,写了这么多希望可以通过这个简单的案例将装饰模式能聊清楚,装饰模式虽然很经典,但是在小永哥的心中,威力最大的还是策略模式,特别是策略模式+模版方法模式,威力巨大,能灵活多变的应对繁琐的业务变化,小永哥好好构思一下业务场景,争取下把和大家聊聊这两种设计模式以及这两种设计模式的组合体,本次就到这了,谢谢大家,晚安。

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

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

相关文章

LeetCode 270:在二叉搜索树中寻找最接近的值(Swift 实战解析)

文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结 摘要 在日常开发中&#xff0c;我们经常需要在一组有序的数据中快速找到最接近某个目标值的元素。LeetCode 第 270 题“Closest Binary Search Tree Value”正是这样一个问题。本文将深入解析该…

WPF 3D图形编程核心技术解析

一、三维坐标系系统 WPF采用右手坐标系系统&#xff0c;空间定位遵循&#xff1a; X 轴 → 右 Y 轴 → 上 Z 轴 → 观察方向 X轴 \rightarrow 右\quad Y轴 \rightarrow 上\quad Z轴 \rightarrow 观察方向 X轴→右Y轴→上Z轴→观察方向 三维坐标值表示为 ( x , y , z ) (x, y,…

暗物质卯引力挂载技术

1、物体质量以及其所受到的引力约束(暗物质压力差) 自然界的所有物体,其本身都是没有质量的。我们所理解的质量,其实是物体球周空间的暗物质对物体的挤压,压力差。 对于宇宙空间中的单个星球而言,它的球周各处压力是相同的,所以,它处于平衡状态,漂浮在宇宙中。 对于星…

comfyui 如何优雅的从Hugging Face 下载模型,文件夹

如下图所示 使用git 下载整个仓库然后把需要的放到对应的位置

通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志

一、TP5.0通过行为&#xff08;Behavior&#xff09;拦截爬虫并避免生成 [ error ] NULL 错误日志 1. 创建行为类&#xff08;拦截爬虫&#xff09; 在 application/common/behavior 目录下新建BlockBot.php &#xff0c;用于识别并拦截爬虫请求&#xff1a; <?php name…

IBM BAW(原BPM升级版)使用教程第七讲

续前篇&#xff01; 一、团队 在 IBM Business Automation Workflow (BAW) 中&#xff0c;团队&#xff08;Team&#xff09; 是流程管理的关键部分&#xff0c;用于定义参与某个流程的用户、角色、组以及服务等。在团队配置中&#xff0c;有许多重要概念&#xff0c;特别是 …

【论文阅读】Efficient and secure federated learning against backdoor attacks

Efficient and secure federated learning against backdoor attacks -- 高效且安全的可抵御后门攻击的联邦学习 论文来源问题背景TLDR系统及威胁模型实体威胁模型 方法展开服务器初始化本地更新本地压缩高斯噪声与自适应扰动聚合与解压缩总体算法 总结优点缺点 论文来源 名称…

Java中的代理机制

目录 什么叫代理 静态代理 优缺点 优点&#xff1a; 缺点&#xff1a; 动态代理 JDK动态代理 核心类 JDK动态代理的实现 步骤 示例 特点 CGLIB动态代理 代理机制对比 总结 什么叫代理 代理模式是一种比较好理解的设计模式。简单来说就是我们使用代理对象来代替…

Jenkins linux安装

jenkins启动 service jenkins start 重启 service jenkins restart 停止 service jenkins stop jenkins安装 命令切换到自己的下载目录 直接用命令下载 wget http://pkg.jenkins-ci.org/redhat-stable/jenkins-2.190.3-1.1.noarch.rpm 下载直接安装 rpm -ivh jenkins-2.190.3-…

Webug4.0靶场通关笔记-靶场搭建方法(3种方法)

目录 一、虚拟机绿色版本 1. 开启phpstudy 2. 访问靶场 二、Docker版本 1.拉取镜像 2.启动镜像 三、源码安装版本 1. 搭建环境 &#xff08;1&#xff09;安装PHPStudy &#xff08;2&#xff09;WeBug4.0靶场源码 &#xff08;3&#xff09;安装Navicat &#xff…

【Web】LACTF 2025 wp

目录 arclbroth lucky-flag whack-a-mole arclbroth 看到username为admin能拿到flag 但不能重复注册存在的用户 这题是secure-sqlite这个库的问题&#xff0c;底层用的是C&#xff0c;没处理好\0字符截断的问题 &#xff08;在 Node.js 中&#xff0c;由于其字符串表示方式…

【日撸 Java 三百行】综合任务 1

目录 Day 10&#xff1a;综合任务 1 一、题目分析 1. 数据结构 2. 相关函数基本知识 二、模块介绍 1. 初始化与成绩矩阵的构建 2. 创建总成绩数组 3. 寻找成绩极值 三、代码与测试 小结 拓展&#xff1a;关于求极值的相关算法 Day 10&#xff1a;综合任务 1 Task&…

华为私有协议Hybrid

实验top图 理论环节 1. 基本概念 Hybrid接口&#xff1a; 支持同时处理多个VLAN流量&#xff0c;且能针对不同VLAN配置是否携带标签&#xff08;Tagged/Untagged&#xff09;。 核心特性&#xff1a; 灵活控制数据帧的标签处理方式&#xff0c;适用于复杂网络场景。 2. 工作…

数据库实验10

设计性实验 1&#xff0e;实验要求 1.编写函数FsumXXX&#xff0c;1~n&#xff08;参数&#xff09;求和&#xff1b; GO CREATE FUNCTION Fsum065 (n INT) RETURNS INT AS BEGIN DECLARE sum INT 0 WHILE n > 0 BEGIN SET sum sum n SET n n - 1 END RETURN sum END …

jflash下载时出现 Could not read unit serial number! 的解决方法

出现的原因是由于Jlink原厂固件SN码是-1 我用的版本是v6.40 解决方法&#xff1a;添加序列号 1.打开&#xff1a;J-Link commander 之后在命令栏输入&#xff1a;exec setsnxxxxxxxx 2.添加序列号到license&#xff0c;打开J-Link License Manager V6.40 jlink-v640下载软件…

Linux 信号终篇(总结)

前文&#xff1a;本文是对信号从产生到被处理的过程中的概念和原理的总结&#xff0c;如果想了解具体实现&#xff0c;请查看前两篇博客&#xff1a;Linux 信号-CSDN博客、Linux 信号&#xff08;下篇&#xff09;-CSDN博客 一、信号的产生 1.1 信号产生的五种条件 ①键盘组…

LVGL对象(Objects)

文章目录 &#x1f9f1; 一、LVGL 中的对象&#xff08;lv\_obj&#xff09;&#x1f539; lv\_obj\_t 的作用 &#x1f9e9; 二、对象的分类结构&#xff08;类比继承&#xff09;&#x1f9f0; 三、对象的创建与销毁✅ 创建对象示例&#xff1a;创建一个按钮❌ 删除对象 &…

服务器配置错误导致SSL/TLS出现安全漏洞,如何进行排查?

SSL/TLS 安全漏洞排查与修复指南 一、常见配置错误类型‌ 弱加密算法与密钥问题‌ 使用弱密码套件&#xff08;如DES、RC4&#xff09;或密钥长度不足&#xff08;如RSA密钥长度<2048位&#xff09;&#xff0c;导致加密强度不足。 密钥管理不当&#xff08;如私钥未加密存…

路由重发布

路由重发布 实验目标&#xff1a; 掌握路由重发布的配置方法和技巧&#xff1b; 掌握通过路由重发布方式实现网络的连通性&#xff1b; 熟悉route-pt路由器的使用方法&#xff1b; 实验背景&#xff1a;假设学校的某个分区需要配置简单的rip协议路由信息&#xff0c;而主校…

C++修炼:stack和queue

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…