【再探】设计模式—适配器、装饰及外观模式

 结构型设计模式是用于设计对象和类之间关系的一组设计模式。一共有7种:适配器模式、装饰器模式、外观模式、桥接模式、组合模式、享元模式及代理模式。

1 适配器模式

需求:在软件维护阶段,已存在的方法与目标接口不匹配,需要个中间类来适配这个方法。

1.1 适配器模式介绍

将一个类的接口转换成客户端期望的目标类格式,使得原本不兼容的类可以一起工作。

图 适配器模式 UML

public class AdapterPattern {

    public static void main(String[] args) {
        SimpleEncrypt simpleEncrypt = new SimpleEncrypt();
        EncryptAdapter adapter = new EncryptAdapter(simpleEncrypt);
        String encrypt = adapter.encrypt("hello adapter");
        System.out.println(encrypt);
    }

    private interface Encrypt {
        String encrypt(String text);
    }

    private static class EncryptAdapter implements Encrypt{

        private static final int ENCRYPT_LENGTH = 15;

        private final SimpleEncrypt simpleEncrypt;

        private EncryptAdapter(SimpleEncrypt simpleEncrypt) {
            this.simpleEncrypt = simpleEncrypt;
        }

        @Override
        public String encrypt(String text) {
            return simpleEncrypt.encrypt(text,ENCRYPT_LENGTH);
        }

    }

    private static class SimpleEncrypt {
        public String encrypt(String text,int length) {
            return text + length;
        }
    }

}

对象适配器

在适配类中关联一共被适配者对象,通过调用被适配者对象的方法来实现适配。

类适配器

实现目标接口的同时,继承被适配者类。

接口适配器

通过一个抽象类来实现接口中的所有方法。具体类通过继承抽象类,根据需求只需要重写特定的方法。

表 适配器种类

1.2 优缺点

优点:

  1. 提高代码的复用性,让原本不兼容的类可以协同工作。
  2. 降低系统耦合度,客户端只与适配器进行交互。

缺点:

  1. 过度使用适配器可能导致系统变得复杂,难以理解和维护,也可能导致性能下降。

2 装饰模式

需求:1)想给给类添加新的功能。而不希望使用继承的方式。2)动态添加及撤销功能。

2.1 装饰模式介绍

在不改变一个对象的接口的前提下,通过创建一个装饰者来包裹真实对象,来动态地增加额外的职责到该对象

图 装饰模式 UML

完全透明

装饰对象和原始对象具有相同的接口,客户端不需要区分装饰对象及原始对象。

半透明

允许装饰对象的接口与原始对象的接口不完全一致。装饰对象的接口可能会比原始对象更宽,但仍需要实现原始对象的接口。

表 装饰模式的两种模式

public class DecoratorPattern {

    public static void main(String[] args) {
        String text = "hello decorator";
        Verifier noEmptyVerifier = new NoEmptyVerifier();
        Verifier minLengthVerifier = new MinLengthVerifier(noEmptyVerifier,7);
        System.out.println(minLengthVerifier.verification(text));
    }

    private interface Verifier {
        boolean verification(String text);
    }

    private static class NoEmptyVerifier implements Verifier {

        @Override
        public boolean verification(String text) {
            return text != null && text.trim().length() > 0;
        }
    }

    private static class MinLengthVerifier implements Verifier {

        private final int DEFAULT_MIN_LENGTH = 15;

        private final Verifier verifier;
        private int minLength = DEFAULT_MIN_LENGTH;

        private MinLengthVerifier(Verifier verifier) {
            this.verifier = verifier;
        }

        public MinLengthVerifier(Verifier verifier, int minLength) {
            this.verifier = verifier;
            this.minLength = minLength;
        }

        @Override
        public boolean verification(String text) {
            return verifier.verification(text) && text.length() > minLength;
        }
    }

}

2.2 优缺点

优点:

  1. 提供了比继承更多的灵活性。
  2. 可以创建一个功能更加强大的对象,通过对一个对象进行多次装饰。
  3. 可以动态的添加及撤销功能。

缺点:

  1. 会产生很多小对象,如果过度使用,可能会导致程序变得复杂且难以维护。
  2. 在某些情况下,调试和排查问题的难度增加。

3 外观模式

需求:与系统交互时,不想与系统的其他业务模块产生关联,希望与一个统一的角色进行交互。

3.1 外观模式介绍

客户端与系统的通信通过一个统一的外观角色进行。

图 外观模式 UML

public class FacadePattern {

    public static void main(String[] args) { // 客户端
        SystemController controller = SystemController.getInstance();
        System.out.println(controller.getUser("facade"));
    }

    private static class SystemController { // 对外的接口

        private static volatile SystemController instance;

        public static SystemController getInstance() {
            if (instance == null) {
                synchronized (SystemController.class) {
                    if (instance == null) {
                        UserService service = new UserService(new UserMapper());
                        instance = new SystemController(service);
                    }
                }
            }
            return instance;
        }

        private final UserService userService;

        private SystemController(UserService userService) {
            this.userService = userService;
        }

        public String getUser(String username) {
            return userService.getUser(username);
        }
    }

    private static class UserService {
        private final UserMapper userMapper;

        private UserService(UserMapper userMapper) {
            this.userMapper = userMapper;
        }

        public String getUser(String username) {
            if (username == null) return "";
            return userMapper.searcherByUsername(username);
        }

    }

    private static class UserMapper {
        public String searcherByUsername(String username) {
            return "用户+" + username;
        }
    }

}

3.2 优缺点

优点:

1)将客户端与系统内部模块分隔开,符合迪米特法则,降低了耦合度。

缺点:

1)不符合开闭原则。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows系统和unbtun系统连接usb 3.0海康可见MVS和红外艾睿相机

一.海康可见USB3.0工业面阵相机 海康usb相机需要去海康官网上下载对应系统的MVS客户端及SDK开发包 海康机器人-机器视觉-下载中心 选择Windows系统和unbtun(我是linux aarch64,所以选择了对应压缩包解压) Windows系统 1.双击安装包进入安装界面&…

【Qt 学习笔记】Qt常用控件 | 输入类控件 | Date/Time Edit的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 输入类控件 | Spin Box的使用及说明 文章编号&#xff1…

【牛客】[HNOI2003]激光炸弹

原题链接:登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 二维前缀和板题。 注意从(1,1)开始存即可,所以每次输入x,y之后,要x,y。 因为m的范围最大为…

nginx--FastCGI

CGI 概念 nginx通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx并回收进程(下次处理有需要新建),最后nginx在返回给客户端…

5.7 线程

进程:解耦稳定,内容之间是不相关的,通信不便利,理论上进程的软硬件的切换时间以及创建开销非常大。--------》资源共享线程实现 线程的问题:本质就是不解耦,一个出问题别的就很有可能出问题,同…

【YoloDeployCsharp】基于.NET Framework的YOLO深度学习模型部署测试平台

YoloDeployCsharp|基于.NET Framework的YOLO深度学习模型部署测试平台 1. 项目介绍2. 支持模型3. 时间测试4. 总结 1. 项目介绍 基于.NET Framework 4.8 开发的深度学习模型部署测试平台,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系…

python实现的信号合成分析系统(DSP)

python实现的信号合成分析系统(DSP) 流程 1、在QT界面上设置好信号频率,采样频率,采样点数 2、使用np构建sin函数 3、使用matplotlib画出 4、分别分析合成信号的FFT频域信息1、效果图 2、示例代码 def btn_com_clicked(self):# 信号合成分析Fs = self.com_fs_edit_value #…

HarmonyOS开发案例:【电子相册】

介绍 如何实现一个简单的电子相册应用的开发,主要功能包括: 实现首页顶部的轮播效果。 实现页面跳转时共享元素的转场动画效果。 实现通过手势控制图片的放大、缩小、左右滑动查看细节等效果。 相关概念 [Swiper]:滑块视图容器&#x…

cmake install命令无法覆盖同名文件

文章目录 1. 问题记录2. 原因排查3. 解决方案 1. 问题记录 我有两个同名文件test.txt,它们内容不同,但时间戳相同(文件属性中的修改时间相同) 我希望在cmake中利用install命令,将${PATH_SRC}/test.txt替换${PATH_DES…

Elasticsearch:使用 MongoDB connector 同步数据到 Elasticsearch

MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。Elasticsearch 是一个高效强…

[CISCN2019 华北赛区 Day1 Web2]ikun

看到提示说一定要找到lv6 这要写脚本来爆破了,用bp是爆破不出来的 发现LV等级都是有参数挂着的 写个脚本看一下 import requests for i in range(1,1000):payload"http://node4.anna.nssctf.cn:28150/shop?page%d"%(i)resrequests.get(payload)if "…

【PCIE】基于PCIE4C的数据传输(四)——使用MSIX中断

基于PCIE4C的数据传输(三)——遗留中断与MSI中断 一文介绍了遗留中断与MSI中断两种中断方式的代码实现,本文继续基于Xilinx UltrascaleHBM VCU128开发板与linux(RHEL8.9),介绍MSIX中断方式的代码实现。本文…

矩阵的压缩存储介绍

引入 概述 特殊矩阵的压缩 对称矩阵 三角矩阵 对角矩阵 稀疏矩阵 三元组存储 十字链表法 示例

java:递归实现的案例

//求第20个月兔子的对数 //每个月兔子对数:1,1,2,3,5,8 public class Test {//求第20个月兔子的对数//每个月兔子对数:1,1,2,3,5,8pu…

《Python编程从入门到实践》day21

# 昨日知识点回顾 设置背景颜色 在屏幕中央绘制飞船 # 今日知识点学习 12.5 重构:方法_check_events()和_update_screen() 12.5.1 方法_check_events() import sys import pygame from Settings import Settings from Ship import Shipclass AlienInvasion:"…

[Maven]IDEA报错-xxx is referencing itself

在IDEA中,执行 mvn clean时报错xxx is referencing itself。 解决方案:https://stackoverflow.com/questions/64246267/maven-error-using-intellij-is-referencing-itself 具体做法:采用上图第二条,将父模块pom文件中的对子模块…

练习题(2024/5/7)

1验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 …

JSP企业快信系统的设计与实现参考论文(论文 + 源码)

【免费】JSP企业快信系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89277688 JSP企业快信系统的设计与实现 摘 要 计算机网络的出现到现在已经经历了翻天覆地的重大改变。因特网也从最早的供科学家交流心得的简单的文本浏览器发展成为了商务和信息的中心…

深入理解Java虚拟机(JVM)

引言: Java虚拟机(JVM)是Java平台的核心组件,它负责将Java字节码转换成平台特定的机器指令,并在相应的硬件和操作系统上执行。JVM的引入使得Java语言具有“一次编写,到处运行”的跨平台特性。本文将深入探…

【练习2】

1.汽水瓶 ps:注意涉及多个输入&#xff0c;我就说怎么老不对&#xff0c;无语~ #include <cmath> #include <iostream> using namespace std;int main() {int n;int num,flag,kp,temp;while (cin>>n) {flag1;num0;temp0;kpn;while (flag1) {if(kp<2){if(…