设计模式之装饰模式解析

装饰模式
1)概述
1.定义

动态地给一个对象增加一些额外的职责,在增加对象功能时,装饰模式比生成子类实现更为灵活。

2.作用

装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。

3.结构图

在这里插入图片描述

4.角色
  • Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

  • ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。

  • Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现,它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

  • ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责,每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

5.代码案例

抽象装饰类

public class Decorator implements Component {//维持一个对抽象构件对象的引用private Component component;//注入一个抽象构件类型的对象public Decorator(Component component){this.component = component;}public void operation() {//调用原有业务方法component.operation();}
}

注意:在Decorator中并未实现operation()方法,而只是调用原有component对象的operation()方法,它没有真正实施装饰,而是提供一个统一的接口,将具体装饰过程交给子类完成。

具体装饰类

public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}public void operation() {super.operation();  //调用原有业务方法addedBehavior();  //调用新增业务方法}//新增业务方法public void addedBehavior() {……}
}

注意:由于在抽象装饰类Decorator中注入的是Component类型的对象,因此可以将一个具体构件对象注入其中,再通过具体装饰类来进行装饰;此外,还可以将一个已经装饰过的Decorator子类的对象再注入其中进行多次装饰,从而对原有功能进行多次扩展。

2)案例-完整解决方案
1.结构图

在这里插入图片描述

Component充当抽象构件类,其子类Window、TextBox、ListBox充当具体构件类,Component类的另一个子类ComponentDecorator充当抽象装饰类,ComponentDecorator的子类ScrollBarDecorator和BlackBorderDecorator充当具体装饰类。

2.代码案例

抽象构件类

//抽象构件类
abstract class Component {public abstract void display();
}

具体构件类

//具体构件类
public class Window extends Component {public void display() {System.out.println("显示窗体!");}
}//具体构件类
public class TextBox extends Component {public void display() {System.out.println("显示文本框!");}
}

抽象装饰类

//抽象装饰类
public class ComponentDecorator extends Component {//维持对抽象构件类型对象的引用private Component component;//注入抽象构件类型的对象public ComponentDecorator(Component component){this.component = component;}public void display() {component.display();}
}

具体装饰类

//黑色边框装饰类:具体装饰类
public class BlackBorderDecorator extends ComponentDecorator {public BlackBorderDecorator(Component component) {super(component);}public void display() {this.setBlackBorder();super.display();}public void setBlackBorder() {System.out.println("为构件增加黑色边框!");}
}

客户端类

public class Client{public  static void main(String[] args) {//使用抽象构件定义Component component,componentBB;//定义具体构件component = new Window();//定义装饰后的构件componentBB = new BlackBorderDecorator(component);componentBB.display();}
}
3)透明装饰模式与半透明装饰模式
1.透明装饰模式

a) 定义

在透明装饰模式中,要求客户端完全针对抽象编程。

客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。

b) 代码案例

//使用抽象构件类型定义对象
Component  c, c1; c = new ConcreteComponent();
c1 = new ConcreteDecorator (c);

c) 注意

透明装饰模式可以让客户端透明地使用装饰之前的对象和装饰之后的对象,无须关心它们的区别。

可以对一个已装饰过的对象进行多次装饰,得到更为复杂、功能更为强大的对象。

在实现透明装饰模式时,要求具体装饰类的operation()方法覆盖抽象装饰类的operation()方法,除了调用原有对象的operation()外还需要调用新增的addedBehavior()方法来增加新行为。

2.半透明装饰模式

a) 定义

用具体装饰类型来定义装饰之后的对象,而具体构件类型还可以使用抽象构件类型来定义。

对客户端而言,具体构件类型无须关心,是透明的;但是具体装饰类型必须指定,这是不透明的。

b) 代码案例

……
//使用抽象构件类型定义
Document  doc; 
doc = new PurchaseRequest();//使用具体装饰类型定义
Approver newDoc; 
newDoc = new Approver(doc);
……

c) 注意

半透明装饰模式可以给系统带来更多的灵活性,设计相对简单,使用起来也非常方便。

不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象。

4)总结
1.优点
  • 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。

  • 可以通过动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。

  • 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出不同行为的组合,得到功能更为强大的对象。

  • 具体构件类与具体装饰类可以独立变化,可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。

2.缺点
  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。

  • 装饰模式提供了一种比继承更加灵活机动的解决方案,但也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

3.适用场景
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

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

不能采用继承的情况

第一类是系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长;

第二类是因为类已定义为不能被继承(如Java语言中的final类)。

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

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

相关文章

银行卡的分类

银行卡是银行账户的一种体现形式,它是由银行机构发行的具有消费信用、转账结算、存取现金等全部或部分功能作为结算支付工具的各类卡的统称。 (1)按是否具有授信额度分类 ①借记卡:借记卡是指发卡银行向申请人签发的,没…

Machine Learning机器学习之向量机(Support Vector Machine,SVM)

目录 前言 算法提出背景: 核心思想: 原理: 应用领域: 一、支持向量机分类(主要变体) 二、构建常见的支持向量机模型 基于Python 中的 Scikit-learn 库构建线性支持向量机(SVM) 三、向…

SQLite中的动态内存分配(五)

返回:SQLite—系列文章目录 上一篇:SQLite中的原子提交(四) 下一篇:SQLite使用的临时文件(二) ​概述 SQLite使用动态内存分配来获得 用于存储各种对象的内存 (例如&#xff1a…

Django开发复盘

一、URL 对于一个不会写正则表达式的蒟蒻来说,在urls.py中就只能傻傻的写死名字,但是即便这样,还会有很多相对路径和绝对路径的问题(相对ip端口的路径),因为我们网页中涉及到页面跳转,涉及到发送…

神经网络:梯度下降法更新模型参数

作者:CSDN _养乐多_ 在神经网络领域,梯度下降是一种核心的优化算法,本文将介绍神经网络中梯度下降法更新参数的公式,并通过实例演示其在模型训练中的应用。通过本博客,读者将能够更好地理解深度学习中的优化算法和损…

帆软报表在arm架构的linux

有朋友遇到一个问题在部署帆软报表时遇到报错。 问 我在 arm架构的linux服务器上部署帆软报表遇到了一个棘手的问题,你有空帮忙看下嘛。 我看后台日志报的错是 需要升级 gcc、libmawt.so ,是系统中缺少Tomcat需要的依赖库,你之前处理过类似…

超级会员卡积分收银系统源码:积分+收银+商城三合一小程序 带完整的安装代码包以及搭建教程

信息技术的迅猛发展,移动支付和线上购物已经成为现代人生活的常态。在这样的背景下,商家对于能够整合收银、积分管理和在线商城的综合性系统的需求日益强烈。下面,罗峰给大家分享一款超级会员卡积分收银系统源码,它集积分、收银、…

vector类(一)

文章目录 vector介绍和使用1.vector的介绍2.vector的使用2.1 vector的定义2.2 vector iterator的使用2.3 vector空间增长问题2.4 vector增删查改2.5 vector迭代器失效问题 3.vector 在OJ中的使用 vector介绍和使用 1.vector的介绍 vector是表示 可变大小数组的 序列容器。 就…

《数据结构学习笔记---第五篇》---链表OJ练习上

目录 CM11链表分割 OR36 链表的回文结构 160.相交链表 141&142环形链表 CM11链表分割 step1:思路分析 1.首先可以想到,我们可以将原链表的元素划分到两个新的链表之中,由于必须保持顺序,所以新链表我们要用尾插。 2.为了方便进行尾插我…

自动化与智能化并行:数字化运维体系助力企业腾飞

文章目录 文章目录 文章目录 一、引言二、数字化运维体系的核心要素三、构建数字化运维体系的策略四、数字化运维体系的实施与挑战主要内容读者对象 一、引言 随着信息技术的迅猛发展,数字化转型已成为企业提升竞争力、实现可持续发展的必由之路。在数字化转型的过…

JSP – 支持WORD上传的富文本编辑器

1.下载示例 https://gitee.com/xproer/zyoffice-tinymce5 2.引入组件 3.配置转换接口 效果 泽优Office文档转换服务(zyOffice) 功能:一键导入Word转HTML,不装控件,不装Office,任意平台兼容(Windows,macOS,Linux,安卓Android,苹果…

【GPU系列】选择最适合的 CUDA 版本以提高系统性能

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

nvm安装以后,node -v npm 等命令提示不是内部或外部命令

因为有vue2和vue3项目多种,所以为了适应各类版本node,使用nvm管理多种node版本,但是当我按教程安装nvm以后,nvm安装以后,node -v npm 等命令提示不是内部或外部命令 首先nvm官网网址:https://github.com/coreybutler/…

数据结构——栈(C语言版)

前言: 在学习完数据结构顺序表和链表之后,其实我们就可以做很多事情了,后面的栈和队列,其实就是对前面的顺序表和链表的灵活运用,今天我们就来学习一下栈的原理和应用。 准备工作:本人习惯将文件放在test.c…

[C++]深入解析:如何计算C++类或结构体的大小

目录 什么是内存对齐 类的成员的存储规则 怎么进行内存对齐(介绍规则与例子讲解) 什么是内存对齐 内存对齐是指将数据存储在内存中时,按照一定的规则让数据排列在规定的地址上,以提高数据访问的效率和速度。在C中,结…

鸿蒙OS开发问题:(ArkTS)【 RSA加解密,解决中文乱码等现象】

RSA加解密开始构建工具类就是举步维艰,官方文档虽然很全,但是还是有很多小瑕疵,在自己经过几天的时间,彻底解决了中文乱码的问题、分段加密的问题。 首先看官方示例代码(以RSA非对称加解密(多次调用doFinal实现分段&a…

TikTok养号怎么做?打破0播放的前提是做好这些

TikTok养号的重要性不必多少,不仅可以在创号初期保障账号安全,后期的账号流量也需要以前期养好账号为前提。下面就给大家分享如何养号的真实操作攻略! 一、为什么要养号 (1)提高系统推荐精准度 系统不了解新账户人设…

spring boot 生成PDF模板文件

1、主要目录 2、maven依赖 <!--工具类依赖--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.19</version></dependency><dependency><groupId>com.alibaba&l…

56. 合并区间(力扣LeetCode)

文章目录 56. 合并区间题目描述思路贪心算法方法一&#xff1a;直接在res中修改代码逻辑梳理&#xff1a; 方法二&#xff1a;在原数组中插入一个超出题目范围的数组代码逻辑梳理&#xff1a; 56. 合并区间 题目描述 以数组 intervals 表示若干个区间的集合&#xff0c;其中单…

律甲法务OA平台:信鸥科技引领法律行业新篇章

随着信息技术的飞速发展&#xff0c;法律行业也迎来了数字化转型的重要时刻。在这个信息化、智能化的时代&#xff0c;如何运用科技手段提升法律服务的质量和效率&#xff0c;成为法律行业亟待解决的问题。信鸥科技&#xff0c;作为业界的佼佼者&#xff0c;凭借其深厚的技术积…