当前位置: 首页 > news >正文

设计模式07-结构型模式(装饰模式/外观模式/代理模式/Java)

4.4 装饰模式

4.4.1 装饰模式的定义

1.动机:在不改变一个对象本身功能的基础上给对象增加额外的新行为

2.定义:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活

4.4.2 装饰模式的结构与分析

image-20241029120615417

//抽象构件类
public interface Component {public void operation();
}
//具体构建类
public class ConcreteComponent implements Component{@Overridepublic void operation() {}
}
//装饰者类
public class Decorator implements Component {private Component component;//要装饰哪个构件public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}
//具体装饰者类
public class ConcreteDecorator extends Decorator{public ConcreteDecorator(Component component) {super(component);}public void preAddOperation() {}public void operation() {preAddOperation();super.operation();postAddOperation();}public void postAddOperation() {}
}
//客户端
public class Main {public static void main(String[] args) {//要装饰的构建ConcreteComponent component = new ConcreteComponent();//创建装饰类Decorator decorator = new Decorator(component);decorator.operation();}
}
  • 装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。

  • 透明装饰模式和半透明装饰模式

**透明装饰模式:**客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。无法在客户端单独调用新增方法addedBehavior()


**半透明装饰模式:**用具体装饰类型来定义装饰之后的对象,而具体构件使用抽象构件类型来定义。最大的缺点在于不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象(此时已经不再是Component类型了)


4.4.3 装饰模式的案例

某软件公司基于面向对象技术开发了一套图形界面构件库——VisualComponent,该构件库提供了大量基本构件,如窗体、文本框、列表框等,由于在使用该构件库时,用户经常要求定制一些特殊的显示效果,如带滚动条的窗体、带黑色边框的文本框、既带滚动条又带黑色边框的列表框等等,因此经常需要对该构件库进行扩展以增强其功能。现使用装饰模式来设计该图形界面构件库。

image-20241029121904589

//抽象构件类
public interface Component {public void display();
}
public class Window implements Component{@Overridepublic void display() {System.out.println("一个窗口");}
}
//抽象装饰类
public class Decorator implements Component{private Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void display() {component.display();}
}
//装饰类
public class BorderDecoration extends Decorator{public BorderDecoration(Component component) {super(component);}public void display() {addBorder();super.display();}public void addBorder() {System.out.println("添加黑色边框");}
}
public class ScrollBarDecorator extends Decorator {public ScrollBarDecorator(Component component) {super(component);}public void display() {addScrollBar();super.display();}public void addScrollBar() {System.out.println("添加滚动条");}
}
//客户端
public class Main {public static void main(String[] args) {Window window = new Window();//添加滚动条ScrollBarDecorator decorator1 = new ScrollBarDecorator(window);//添加黑边框BorderDecoration decorator2 = new BorderDecoration(decorator1);decorator2.display();}
}
4.4.4 装饰模式的优缺点
优点缺点
1.装饰模式可以动态的扩展一个对象的功能,且比继承简洁,不会导致类的个数急剧增多1.装饰模式进行系统设计时,会产生很多小对象,占用资源
2.可以对一个对象多次装饰2.比继承更容易犯错
3.构件类和装饰类可以独立变化,无需修改源代码符合开闭原则
4.4.5 装饰模式的适用场景
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责

  • 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式

4.5 外观模式

4.5.1 外观模式的定义

**1.模式动机:**一个客户类需要和多个业务类交互,有时候这些需要交互的业务类会作为一个整体出现,如何简化这种主系统和子系统之间的交互。

**2.模式定义:**为子系统中的一组接口提供一个统一的入口,外观模式定义了一个高层接口,这个接口使得子系统更加容易使用,外部与子系统的通信通过一个统一的外观对象进行。

4.5.2 外观模式的结构与分析

image-20241031150738873

  • 外观对象是迪米特法则的一种具体实现。
  • 子系统符合单一职责原则。
  • 但是当新加入一个子系统时,需要修改子系统角色,这不符合开闭原则。
  • 一个系统可能有多个外观类
  • 不要通过外观类给子系统增加行为
  • 为了在增加外观类的时候符合开闭原则,可以增加一个抽象外观类
public class Facade {private SubSystem1 subSystem1 = new SubSystem1();private SubSystem2 subSystem2 = new SubSystem2();public void method() {subSystem1.method1();subSystem2.method2();}
}
public class SubSystem1 {public void method1() {}
}
public class SubSystem2 {public void method2() {}
}
4.5.3 外观模式的案例

现在考察一个电源总开关的例子,以便进一步说明外观模式。为了使用方便,一个电源总开关可以控制四盏灯、和一台电视机的启动和关闭。通过该电源总开关可以同时控制上述所有电器设备,使用外观模式设计该系统。

image-20241031153223590
public class Light {private String location;public Light(String location) {this.location = location;}public void on() {System.out.println("打开" + location + "的灯");}public void off() {System.out.println("关闭" + location + "的灯");}
}
public class TV {public void on() {System.out.println("打开电视");}public void off() {System.out.println("关闭电视");}
}
public class Facade {private Light[] lightArray = new Light[4];private TV tv;public Facade() {lightArray[0] = new Light("客厅");lightArray[1] = new Light("厨房");lightArray[2] = new Light("卫生间");lightArray[3] = new Light("卧室");tv = new TV();}public void on() {lightArray[0].on();lightArray[1].on();lightArray[2].on();lightArray[3].on();tv.on();}public void off() {lightArray[0].off();lightArray[1].off();lightArray[2].off();lightArray[3].off();tv.off();}
}
public class Main {public static void main(String[] args) {Facade facade = new Facade();facade.on();facade.off();}
}
4.5.4 外观模式的优缺点
优点缺点
1.对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易1.不能很好地限制客户端直接使用子系统类
2.对客户端和子系统进行解耦2.如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则
3.子系统的变化独立,不会影响到其他子系统和客户端
4.5.5 外观模式的适用场景
  • 要为访问一系列复杂的子系统提供一个简单入口

  • 客户端程序与多个子系统之间存在很大的依赖性

  • 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而是通过外观类建立联系,降低层之间的耦合度

4.6 代理模式

4.6.1 代理模式的定义

**1.模式动机:**通过引入一个新的对象来实现对真实对象的操作,或者将新的对象作为真实对象的一个替身,引入代理对象来间接访问一个对象

2.模式定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用

4.6.2 代理模式的结构与分析
image-20241031154722704
public interface Subject {public void request();
}
public class Real implements Subject{@Overridepublic void request() {}
}
public class Proxy implements Subject{private Real real = new Real();public void preRequest() {}@Overridepublic void request() {preRequest();real.request();postRequest();}public void postRequest() {}
}
4.6.3 代理模式的案例
  • 保护代理:

在一个论坛中已注册用户和游客的权限不同,已注册的用户拥有发帖、修改自己的注册信息、修改自己的帖子等功能;而游客只能看到别人发的帖子,没有其他权限。使用代理模式来设计该权限管理模块。

image-20241031160121403

public interface Permission {public void readBolg();public void writeBolg();public void updateBolg();public void updateUserInfo();
}public class RealPermission implements Permission{@Overridepublic void readBolg() {System.out.println("阅读博客");}@Overridepublic void writeBolg() {System.out.println("写博客");}@Overridepublic void updateBolg() {System.out.println("修改博客");}@Overridepublic void updateUserInfo() {System.out.println("修改用户信息");}
}public class ProxyPermission implements Permission{private int state;private RealPermission permission;public ProxyPermission(int state) {this.state = state;permission = new RealPermission();}@Overridepublic void readBolg() {permission.readBolg();}@Overridepublic void writeBolg() {if (state == 0) {System.out.println("游客模式不能写博客");} else {permission.writeBolg();}}@Overridepublic void updateBolg() {if (state == 0) {System.out.println("游客模式不能更改博客");} else {permission.updateBolg();}}@Overridepublic void updateUserInfo() {if (state == 0) {System.out.println("游客模式不能更改信息");} else {permission.updateUserInfo();}}
}
4.6.4 代理模式的优缺点
优点缺点
1.能够协调调用者和被调用者,在一定程度上降低了系统的耦合度1.增加了代理对象,有些类型的代理模式可能会造成请求的处理速度变慢
2.客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则2.实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂
4.6.5 代理模式的适用场景
代理模式描述
远程代理当客户端对象需要访问远程主机中的对象时
虚拟代理当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时
缓冲代理当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时
保护代理当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时
智能引用代理当需要为一个对象的访问(引用)提供一些额外的操作
防火墙代理保护目标不让恶意用户接近。
同步化代理使几个用户能够同时使用一个对象而没有冲突。
Copy-on-Write代理把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作。

相关文章:

设计模式07-结构型模式(装饰模式/外观模式/代理模式/Java)

4.4 装饰模式 4.4.1 装饰模式的定义 1.动机:在不改变一个对象本身功能的基础上给对象增加额外的新行为 2.定义:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活 4.4.2 装饰模式的结构…...

C# 广播技术——发现局域网设备技术——

一广播技术应用 客户端发现与管理:软件可以通过广播消息来发现网络中的客户端,从而方便对客户端进行集中管理和监控。服务通知:向所有客户端广播重要的通知、更新或警告信息,确保客户端及时了解相关情况。资源共享与分配&#xf…...

【QA】windows和linux陷入系统调用后有什么区别?

最近被某面试官的这个问题拷打,当场脸烧起来… 首先讲讲系统调用: 系统调用是操作系统为调用者提供服务的接口,以便程序员聚焦于业务问题。分为文件操作,内存分配,进程管理等等。用户使用系统调用后会触发软中断&…...

Github 2024-11-01 开源项目月报 Top19

根据Github Trendings的统计,本月(2024-11-01统计)共有19个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目9TypeScript项目3JavaScript项目3Svelte项目1Jupyter Notebook项目1Ruby项目1HTML项目1Rust项目1Java项目1C++项目1Go项目1Python中的…...

Python实现深度学习模型预测控制(tensorflow)DL-MPC(Deep Learning Model Predictive Control

链接:深度学习模型预测控制 (如果认为有用,动动小手为我点亮github小星星哦),持续更新中…… 链接:WangXiaoMingo/TensorDL-MPC:DL-MPC(深度学习模型预测控制)是基于 P…...

Anki插件Export deck to html的改造

在Anki中进行复习时,每次只能打开一条笔记。如果积累了很多笔记,有时候会有将它们集中输出成一个pdf进行阅读的想法。Anki插件Export deck to html(安装ID:1897277426)就有这个功能。但是,这个插件目前存在…...

csdn 记载文章十分缓慢

现象:其它网站能够正常访问,但只要点击某个 csdn 页面就会等很久 (本文只针对 csdn 网页,其他网页出现类似情况可以同样处理) 产生这种现象的原因: 这种情况很有可能是在访问 CSDN 主页时,需要向…...

python通过pyperclip库操作剪贴板

pyperclip介绍 pyperclip是一个python库用于操作剪贴板,可以非常方便地将文本复制到剪贴板或从剪贴板获取文本。 通过pip进行安装:pip install pyperclip pyperclip的github地址 pyperclip使用 复制到剪贴板 import pypercliptext "Hello, Wo…...

LSTM——长短期记忆神经网络

目录 1.LSTM 工作原理 2.LSTM的代码实现 3.代码详解 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN),用于解决长序列中的长期依赖问题。它通过引入门机制,控制信息的流入、保留和输出&…...

10进阶篇:运用第一性原理解答“是什么”类型题目

在667分析题题型中,关于“如何做”和“好处是什么”的题目,许多同学都能较好地运用前述的667作答地图开展答题,但是唯独在“是什么”类型题目(也可以叫做认识型题目),不知从何下手。这种题目通常要求我们理解、分析,并展望未来的发展方向,而结构化、逻辑清晰的答案往往…...

【elkb】索引生命周期管理

索引生命周期管理 Index lifecycle management(索引生命周期管理)是elasticsearch提供的一种用于自动管理索引的生命周期的功能。允许使用者定义索引的各个阶段,从创建至删除。并允许使用者在每个阶段定义索引需要执行的特定动作。这些动作包含索引创建&#xff0c…...

江协科技STM32学习- P25 UART串口协议

🚀write in front🚀 🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝​…...

15分钟学 Go 第 22 天:包的使用

第22天:包的使用 欢迎来到Go语言的第22天!今天,我们将深入探讨如何创建和使用包。通过学习包的使用,你将能够更好组织你的代码,提高复用性和可维护性。 1. 包的概念 在Go语言中,包是代码的基本组织单位。…...

【Leecode】Leecode刷题之路第35天之搜索插入位置

题目出处 35-搜索插入位置-题目出处 题目描述 个人解法 思路: 1.依次遍历数组,看目标值是否在数组中 2.如果不在,将目标值插入数组(涉及到数组移动、扩容),返回下标代码示例:(Java…...

速盾:海外cdn高防

随着互联网的快速发展,网站的安全性和稳定性变得越来越重要。尤其是对于大型企业和电商平台来说,保护用户数据和维护网站稳定运行是至关重要的。为了应对日益增长的网络攻击和恶意访问,海外CDN高防服务成为了一种非常受欢迎的解决方案。 首先…...

图书管理系统(JDBC)

AdminUser是管理员类 NormalUser是用户类 AddOperation是增加图书类 BorrowOperation是借书类 DelOperation是删除图书类 ExitOperation是退出类 FindOperation是查找图书类 IOPeration是接口 ReturnOperation是还书类 ShowOperation是显示所有图书类 注意&#xff1a…...

模板初阶及STL简介

目录 一.模板初阶 1.泛型函数 2.函数模板 1.函数模板概念 2.函数模板使用格式 3.函数模板的原理 4.函数模板的实例化 5.模板参数的匹配原则 3.类模板 1.类模板的定义格式 2.类模板的实例化 二.STL简介 1.什么是STL 2.STL的版本 3.STL的六大组件 4.如何学习STL …...

UE5 不同的编译模式下,module的组织形式

由于最近在琢磨UE5.4这个引擎,在学习过程中,碰到了一些非常有意思的事情,我在尝试把之前写的一些底层库搬到UE里面,比如底层库,网络库等等,我通过建立module,将这些库用源代码的方式整合进了UE5…...

【ms-swift 大模型微调实战】

安装环境 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscope vllm ‘ms-swift[llm]’ -U 下载模型 modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir ./Qwen2.5-7B-Instruct 微调 实验环境:…...

Linux:网络基础

计算机是人的工具,人需要协作,于是有了网络 专用服务器->专用计算机 局域网:随着计算机的数量增加,通过交换机和路由器连接计算机 广域网:将远隔千里的计算机都连在一起 协议 协议就是约定俗成 计算机之间用光信号…...

mysql 的内连接、左连接、右连接有什么区别?

在MySQL中,内连接、左连接和右连接是三种常见的连接类型,它们用于通过共享一个或多个字段的值,将两个或多个表组合在一起进行查询。以下是这三种连接类型的详细区别: 一、内连接(INNER JOIN) 定义&#x…...

update-alternatives(选择工具)

0 Preface/foreword 1 update-alternatives介绍 1.1 选项和用法 1.2 install用法 update-alternatives --install <link> <name> <path> <priority> [--slave <link> <name> <path>] link&#xff1a;符号链接&#xff08;软链…...

php解密,sg11解密-sg15解密 如何由sourceGuardian11-sourceGuardian15加密(sg11加密~sg15加密)的源码

sg11加密~sg11加密的PHP文件运行需安装SG11加密-SG15加密组件使用、支持WINDOW及LINUX各版本 sg11解密(SourceGuardian)-sg15解密(SourceGuardian)&#xff0c;号称目前最安全的组件加密已可以解密&#xff0c;解密率99.9%&#xff0c;基本可以直接使用&#xff0c;代码特征是…...

b站小土堆PyTorch视频学习笔记(二)

Dataloader:提供不同类型的数据集&#xff1b;为后面的网络提供不同的数据形式 Dataset&#xff1a;提供一种方式去获取数据及其label&#xff08;标签&#xff09; 主要实现以下两个功能&#xff1a; {如何获取每一个数据及其lable&#xff1b;告诉我们总共有多少数据} fr…...

Linux的压缩及其解压命令

1、zip文件 压缩 zip linux.zip linux 解压 unzip linux.zip 2、gz文件 压缩 gzip 1.tar 解压 gzip -d 1.tar.gz 3、tar文件(tar可打/解包&#xff0c;压缩/解压文件) 打包 tar -cf 1.rar test 解包 tar -xf 1.tar 解压gz并解包 tar -xjvf archive_name.tar.bz2&#…...

GXYCTF2019:gakki

把题目给的附件解压后给了张图片&#xff0c;顺带着瞟一眼属性&#xff0c;没有值得注意的 binwalk检测一手&#xff0c;看见有个rar压缩包 提取出来的压缩包是有密码的&#xff0c;但是题目并没有给出获取密码的途径&#xff0c;所以先爆破试试&#xff0c;用最常用的四位数爆…...

顺序表(C 语言)

目录 一、线性表二、顺序表1. 静态顺序表2. 动态顺序表2.1 动态顺序表的实现分析2.2 动态顺序表的实现2.3 动态顺序表存在的问题 三、与数组有关的面试题1. 移除元素2. 删除有序数组中的重复项 一、线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元…...

一:时序数据库-Influx应用

目录 0、版本号 1、登录页面 2、账号基本信息 3、数据库案例 4、可视化 5、java案例 0、版本号 InfluxDB v2.4.0 1、登录页面 http://127.0.0.1:8086/signin 账号&#xff1a;自己账号 密码&#xff1a;自己密码 2、账号基本信息 查看用户id和组织id&#xff01;&…...

Word文档丢失抢救方法:15 个 Word 文档恢复工具

MS Word 文档恢复的重要性 对于严重依赖 Microsoft Word 创建和编辑文档的个人和企业来说&#xff0c;MS Word 文档恢复是一个至关重要的方面。 文件损坏、系统崩溃和其他意外事件可能会导致 Word 文档中存储的重要数据丢失。 及时恢复这些文档有助于节省时间、精力和资源。 本…...

关于自动驾驶等级相关知识

本文主要介绍自动驾驶等级的一下知识&#xff0c;在介绍之前&#xff0c;首先要介绍一些基本知识&#xff0c;然后介绍自动驾驶不同等级 1、自动驾驶相关知识 监控和判断&#xff08;OEDA&#xff09;&#xff1a;指对车辆周围的物体和事件进行检测和感知&#xff0c;并给出应…...