设计模式之适配器与装饰器

news2024/9/23 17:15:48

目录

适配器模式

简介

角色

使用

优缺点

使用场景

装饰器模式

简介

优缺点

模式结构

使用

使用场景


适配器模式

简介

允许将不兼容的对象包装成一个适配器类,使得其他类可以通过适配器类与原始对象进行交互,从而提高兼容性

角色

目标角色:该角色定义把其他类转换为何种接口,也就是我们的期望接口

源角色:你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象

适配器角色:适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:通过继承或是类关联的方式把源角色转换为目标角色

使用

1.定义目标接口:创建一个目标接口,这个接口定义了客户端所期望的功能。

2.创建原始类:客户端原始功能

3.创建适配器类:创建一个适配器类,该类实现了目标接口,同时包装了不兼容的原始对象,使得客户端可以通过目标接口与原始对象进行交互

4.使用目标接口:客户端代码使用目标接口与适配器进行交互

// 目标接口  
interface Target {  
    void request();  
}  
  
// 原始类  
class Adaptee {  
    void specificRequest() {  
        System.out.println("Adaptee's specific request.");  
    }  
}  
  
// 适配器类  
class Adapter implements Target {  
    private Adaptee adaptee;  
  
    public Adapter(Adaptee adaptee) {  
        this.adaptee = adaptee;  
    }  
  
    @Override  
    public void request() {  
        adaptee.specificRequest();  
    }  
}  
  
// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        Adaptee adaptee = new Adaptee();  
        Target target = new Adapter(adaptee);  
        target.request();  
    }  
}

        目标接口Target,它定义了一个request方法。我们还有一个原始类Adaptee,它有一个名为specificRequest的方法。我们的适配器类Adapter实现了目标接口,并且包装了原始类的specificRequest方法。在客户端代码中,我们创建了一个原始类的实例和一个适配器类的实例,然后将适配器类的实例传递给目标接口的引用。当我们调用目标接口的request方法时,实际上是适配器类在调用原始类的specificRequest方法

优缺点

优点:

        1.能提高类的透明性和复用,现有的类复用但不需要改变。

        2.目标类和适配器类解耦,提高程序的扩展性。

        3.在很多业务场景中符合开闭原则

缺点:

        1.适配器编写过程需要全面考虑,可能会增加系统的复杂性

        2.增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱

使用场景

        1.一个类的接口转换成期望的另一个接口,使不能兼容的两个类一起工作

        2.想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作

        3.在软件维护期间,由于不同产品或不同厂家造成功能类似而接口不相同的情况,可以通过适配器模式来解决

        使用适配器模式可以降低不同组件之间的耦合度,提高系统的可扩展性和可维护性。同时,适配器模式还可以解决不同系统之间的接口不兼容问题

装饰器模式

简介

        在不改变现有对象结构下,动态的给对象添加一些功能

优缺点

优点

        1.装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用

        2.通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果

        3.装饰器模式完全遵守开闭原则

缺点

        装饰器模式会增加许多子类,过度使用会增加程序得复杂性

模式结构

角色:

        抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象

        具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责

        抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能

        具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任

结构图:

使用

1.创建接口

public interface Shape {  
    double getArea();  
}

2.接口具体实现类

public class Rectangle implements Shape {  
    private double length;  
    private double width;  
  
    public Rectangle(double length, double width) {  
        this.length = length;  
        this.width = width;  
    }  
  
    @Override  
    public double getArea() {  
        return length * width;  
    }  
}

3.创建抽象装饰器

public abstract class ShapeDecorator implements Shape {  
    protected Shape decoratedShape;  
  
    public ShapeDecorator(Shape shape) {  
        this.decoratedShape = shape;  
    }  
  
    @Override  
    public double getArea() {  
        return decoratedShape.getArea();  
    }  
}

4.创建具体装饰器

public class RectangleWithBorder extends ShapeDecorator {  
    private double borderWidth;  
  
    public RectangleWithBorder(Shape shape, double borderWidth) {  
        super(shape);  
        this.borderWidth = borderWidth;  
    }  
  
    @Override  
    public double getArea() {  
        return decoratedShape.getArea() + borderWidth * decoratedShape.getArea();  
    }  
}

5.使用

public class Main {  
    public static void main(String[] args) {  
        Shape rectangle = new Rectangle(5, 5);  
        Shape rectangleWithBorder = new RectangleWithBorder(rectangle, 1); // 给矩形添加边框宽度为1的装饰器  
        System.out.println("Rectangle area: " + rectangle.getArea()); // 输出:Rectangle area: 25.0  
        System.out.println("Rectangle with border area: " + rectangleWithBorder.getArea()); // 输出:Rectangle with border area: 27.0  
    }  
}

使用场景

1.扩展功能:当您想要扩展一个类的功能时,可以使用装饰器模式来添加新的责任,而不需要修改原有类的代码。这使得代码更加灵活,易于维护

2.动态变化:如果需要在运行时根据需要动态地改变对象的行为,可以使用装饰器模式

3.统一接口:如果有一组具有相似功能但是又不完全相同的类,可以使用装饰器模式来统一它们的接口,使得在使用它们时不需要关心具体的类

4.延迟加载:如果某些数据是可选的,可以在需要时才加载,使用装饰器模式可以实现延迟加载的功能

5.处理复杂对象:当涉及到复杂的对象结构时,装饰器模式可以简化代码。通过将不同的行为封装到不同的装饰器中,可以组合这些装饰器来创建具有不同行为的对象

        装饰器模式适用于在不修改原有代码的基础上,动态地给对象添加新的行为。它适用于需要在运行时动态地改变对象行为或者需要统一接口的场景。

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

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

相关文章

np.numpy, np.reshape, np.cumsum方法速查

1 np.numpy() 创建一个数组 state[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]] state2np.array(state) print(state) print(state2)[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] [[ 1 2 3 4 5] [ 6 7 8 9 10] [11 12 13 14 15]] 2 np.reshape() 常用于矩阵规…

向日葵光伏发电

“光伏向日葵”是一个可移动、可调节的光伏储能系统。系统使用全球定位跟踪算法,使叶片(光伏板)跟随太阳移动的轨迹自动调节叶片方向、角度及收放状态,保证了叶片与太阳始终保持着最佳的发电角度,实现全时段发电效率最…

Acrobat Pro DC 2023 for Mac

Acrobat Pro DC是一款由Adobe开发的专业级PDF编辑和管理软件。作为PDF行业的标准工具,它提供了广泛的功能和工具,适用于个人用户、企业和专业人士。 Acrobat Pro DC具备丰富的编辑功能,可以对PDF文件进行文本编辑、图像编辑和页面重排等操作。…

大数据计算引擎 EasyMR 如何简单高效管理 Yarn 资源队列

设想一下,作为一个开发人员,你现在所在的公司有一套线上的 Hadoop 集群。A部门经常做一些定时的 BI 报表,B部门则经常使用软件做一些临时需求。那么他们肯定会遇到同时提交任务的场景,这个时候到底应该如何分配资源满足这两个任务…

OB Cloud上新,4.1版本现已全面开放

2022 年 8 月 10 日,OceanBase 宣布 OceanBase 公有云服务全球开服,帮助不同规模客户,在全球不同区域,享受同样优质的企业级数据库产品与服务。 经过近一年的发展,公有云业务取得了长足的发展,去年对客收入…

截取字符串 substr lastIndexOf

效果图 代码 item.content.substr(item.content.lastIndexOf(/) 1, item.content.length - item.content.lastIndexOf(/)) 就可以得到

linux系统维护篇:/dev/null 妙用

介绍 /dev/null 是一个特殊的设备文件,该文件接收的所有数据都会被丢弃(不显示、不打印、不记录),类似于黑洞。 场景 场景1,执行命令有输出信息(正确和错误),且直接通过输出内容判断…

python -- 实现路径的匹配,剔除掉指定路径,并保存路径

python – 实现路径的匹配,剔除掉指定路径,并保存路径 在处理nc数据时,由于部分数据在插值的过程中,存在过多的0值,使得在制作标签时该时刻的数据出现报错,但是对于一年的数据量来说,无关紧要&…

剑指 Offer 66. 构建乘积数组(中等)

题目: class Solution { public:vector<int> constructArr(vector<int>& a) {int len a.size();if(len0) return {};vector<int> b(len, 1);for(int i1;i<len;i){ //先计算b[i]下三角的乘积。由图可看出b[1]乘的是a[0]b[i]b[i-1]*a[i-1];}int t…

【数据结构】 二叉树面试题讲解->壹

文章目录 &#x1f30f;引言&#x1f340;[相同的树](https://leetcode.cn/problems/same-tree/description/)&#x1f431;‍&#x1f409;题目描述&#xff1a;&#x1f431;‍&#x1f453;示例&#xff1a;&#x1f4cc;示例一&#x1f4cc;示例二&#x1f4cc;示例三 &…

趣解开闭原则之《我发誓!再也不买一体机了》

〇、小故事 小王大学毕业后&#xff0c;找了一份像样的工作&#xff0c;早八晚五轻松自在&#xff0c;并且收入也不错。自从大学毕业后&#xff0c;家里用的电脑还是他上大学的时候用了四年的电脑&#xff0c;配置性能早已跟不上现在的时代了。他决定用自己赚的工资买一台家用…

计算机毕设之基于python+django+mysql的影片数据爬取与数据分析(包含源码+文档+部署教程)

影片数据爬取与数据分析分为两个部分&#xff0c;即管理员和用户。该系统是根据用户的实际需求开发的&#xff0c;贴近生活。从管理员处获得的指定账号和密码可用于进入系统和使用相关的系统应用程序。管理员拥有最大的权限&#xff0c;其次是用户。管理员一般负责整个系统的运…

三步完成echers展示离线地图

1.首先要去阿里云提供的地图选择器网站选择你需要下载的地图矢量数据。链接 以湖北省为例&#xff1a; 2.复制上图中的JSON API&#xff0c;在浏览器输入json api链接&#xff0c;可以看到数据格式是很规整的json数据&#xff0c;在浏览器中右键保存为json格式数据&#xff0c…

python实现pdf双页文档转png图片,png图片裁剪为左右两等分,再合并为新的pdf单页文档

一、问题引入 现有pdf双页文档如下&#xff1a; 现按照以下页码次序对pdf双页文档进行裁剪和拼接&#xff0c;其中有两点需要特别注意&#xff0c;一是封面页只裁剪中间部分&#xff0c;二是文档是从右往左的顺序排版的 二、python程序 import os import office from PIL …

vue3 组合式api中 ref 和$parent 的使用

ref 的使用 vue3中&#xff0c; 在 组件中添加一个 component ref“xxx” &#xff0c;就可以在父组件中得到 子组件的 dom 对象&#xff0c; 以及 虚拟的 dom 对象&#xff0c; 有了虚拟 dom, 我们就可以在父组件中控制子组件的显示了 ref 的使用方法 vue3中ref 的特点 以上…

h5 ws 客户端 监听ws服务器广播的信息

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>AI智能写作</title><!-- Bootstrap CSS --><meta charset"utf-8"><meta name"viewport" content"widt…

常用Web漏洞扫描工具汇总(持续更新中)

常用Web漏洞扫描工具汇总 常用Web漏洞扫描工具汇总1、AWVS&#xff0c;2、OWASP Zed&#xff08;ZAP&#xff09;&#xff0c;3、Nikto&#xff0c;4、BurpSuite&#xff0c;5、Nessus&#xff0c;6、nmap7、X-ray还有很多不是非常知名&#xff0c;但可能也很大牌、也较常见的。…

气传导耳机品牌推荐哪些?2023气传导耳机排行榜分享

​气传导耳机的出现&#xff0c;为我们带来了更加便捷和舒适的使用体验&#xff0c;同时也让我们能够更加自由地享受音乐和其他娱乐内容。因此&#xff0c;如果你正在寻找一款高品质的气传导耳机&#xff0c;不妨考虑一下以下气传导耳机的推荐&#xff01; Top1&#xff1a;南…

【斗破苍穹】天府联盟成立,三大势力加入,美杜莎缺席副盟主

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析【斗破苍穹】 在斗破苍穹中&#xff0c;身为主角的萧炎可以说建立了不少势力&#xff0c;最开始是磐门&#xff0c;这算是一个很小的势力&#xff0c;成员都是迦南学院的学生&#xff0c;而且战力普遍不高&#xff0c;全靠…

从零开始的Hadoop学习(六)| HDFS读写流程、NN和2NN工作机制、DataNode工作机制

1. HDFS的读写流程&#xff08;面试重点&#xff09; 1.1 HDFS写数据流程 1.1.1 剖析文件写入 &#xff08;1&#xff09;客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件&#xff0c;NameNode检查目标文件是否已存在&#xff0c;父目录是否存在。 &#x…