设计模式(七)装饰模式

相关文章
设计模式系列

1.装饰模式简介

装饰模式介绍

装饰模式是结构型设计模式之一,不必改变类文件和使用继承的情况下,动态地扩展一个对象的功能,是继承的替代方案之一。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

定义

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

装饰模式结构图

  • Component:抽象组件,给对象动态的添加职责。
  • ConcreteComponent:组件具体实现类。
  • Decorator:抽象装饰者,继承Component,从外类来拓展Component类的功能,但对于Component来说无需知道Decorator的存在。
  • ConcreteDecorator:装饰者具体实现类。

2.装饰模式的简单实现

装饰模式在现实生活中有很多例子,比如给一个人穿上各种衣服,给一幅画涂色上框等等,这次我要举得例子有些不同,举一个武侠修炼武功的例子:杨过本身就会全真剑法,有两位武学前辈洪七公和欧阳锋分别传授杨过打狗棒法和蛤蟆功,这样杨过除了会全真剑法还会打狗棒法和蛤蟆功。

抽象组件(Component)

作为武侠肯定要会使用武功的,我们先定义一个武侠的抽象类,里面有使用武功的抽象方法:

public abstract class Swordsman {/*** Swordsman武侠有使用武功的抽象方法*/public abstract void attackMagic();
}

组件具体实现类(ConcreteComponent)

被装饰的具体对象,在这里就是被教授武学的具体的武侠,他就是杨过,杨过作为武侠当然也会武学,虽然不怎么厉害:

public class YangGuo extends Swordsman{@Overridepublic void attackMagic() {//杨过初始的武学是全真剑法System.out.println("杨过使用全真剑法");}
}

抽象装饰者(Decorator)

抽象装饰者保持了一个对抽象组件的引用,方便调用被装饰对象中的方法。在这个例子中就是武学前辈要持有武侠的引用,方便教授他武学并“融会贯通”:

public abstract class Master extends Swordsman{private Swordsman mSwordsman;public Master(Swordsman mSwordsman){this.mSwordsman=mSwordsman;}@Overridepublic void attackMagic() {mSwordsman.attackMagic();}
}

装饰者具体实现类(ConcreteDecorator)

这个例子中用两个装饰者具体实现类,分别是洪七公和欧阳锋,他们负责来传授杨过新的武功:

public class HongQiGong extends Master {public HongQiGong(Swordsman mSwordsman) {super(mSwordsman);}public void teachAttackMagic(){System.out.println("洪七公教授打狗棒法");System.out.println("杨过使用打狗棒法");}@Overridepublic void attackMagic() {super.attackMagic();teachAttackMagic();}
}
public class OuYangFeng extends Master {public OuYangFeng(Swordsman mSwordsman) {super(mSwordsman);}public void teachAttackMagic(){System.out.println("欧阳锋教授蛤蟆功");System.out.println("杨过使用蛤蟆功");}@Overridepublic void attackMagic() {super.attackMagic();teachAttackMagic();}
}

 客户端调用

经过洪七公和欧阳锋的教导,杨过除了初始武学全真剑法又学会了打狗棒法和蛤蟆功:

 

public class Client {public static void main(String[] args){//创建杨过YangGuo mYangGuo=new YangGuo();//洪七公教授杨过打狗棒法,杨过会了打狗棒法HongQiGong mHongQiGong=new HongQiGong(mYangGuo);mHongQiGong.attackMagic();//欧阳锋教授杨过蛤蟆功,杨过学会了蛤蟆功OuYangFeng mOuYangFeng=new OuYangFeng(mYangGuo);mOuYangFeng.attackMagic();}
}

3.装饰模式的优缺点和使用场景

优点
  • 通过组合而非继承的方式,动态的来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
  • 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
  • 具体组件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体组件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
缺点
  • 装饰链不能过长,否则会影响效率。
  • 因为所有对象都是继承于Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),如果基类改变,势必影响对象的内部。
  • 比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐,所以只在必要的时候使用装饰者模式。
使用场景
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能可以动态的撤销。
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

4.装饰模式和代理模式

在上一篇文章设计模式之代理模式中我们讲到了代理模式,你会觉得代理模式和装饰模式有点像,都是持有了被代理或者被装饰对象的引用。它们两个最大的不同就是装饰模式对引用的对象增加了功能,而代理模式只是对引用对象进行了控制却没有对引用对象本身增加功能。

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

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

相关文章

【日常聊聊】Sora- 探索AI视频模型的无限可能

🍎个人博客:个人主页 🏆个人专栏:日常聊聊 ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 方向一:技术解析 方向二:应用场景 方向三:未来展望 方向四:伦理与创意 方向…

[linux][异常检测] hung task, soft lockup, hard lockup, workqueue stall

hung task,soft lockup,hard lockup,workqueue stall 是 linux 内核中的异常检测机制,这 4 个检测均是通过时间维度上的检测来判断异常。 在时间维度上的检测机制,有两个核心的点: (1&#xff…

web组态插件

插件演示地址:http://www.byzt.net 关于组态软件,首先要从组态的概念开始说起。 什么是组态 组态(Configure)的概念来自于20世纪70年代中期出现的第一代集散控制系统(Distributed Control System)&#xf…

紫外-可见吸收光谱法(UV-Vis)是最常用吸收光谱技术 市场持续扩大

紫外-可见吸收光谱法(UV-Vis)是最常用吸收光谱技术 市场持续扩大 紫外-可见吸收光谱法,也称为紫外-可见分光光度法,简称UV-Vis,利用样品分子在紫外和可见光激发下产生电子能级跃迁形成的吸收光谱,对元素进行…

基于Java SSM框架实现高校网课管理系统项目【项目源码+论文说明】

基于java的SSM框架实现高校网课管理系统演示 摘要 随着移动应用技术的发展,越来越多的学生借助于移动手机、电脑完成生活中的事务,许多的行业也更加重视与互联网的结合,以提高教学的教育水平和寻求更高的经济利益。针对高校网课管理系统&…

猫头虎分享已解决Bug || 解决SyntaxError: Unexpected token o in JSON at position 1

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

HashMap的put()方法执行流程

HashMap的数据结构在jdk1.8之前是数组链表,为了解决数据量过大、链表过长是查询效率会降低的问题变成了数组链表红黑树的结构,利用的是红黑树自平衡的特点。 链表的平均查找时间复杂度是O(n),红黑树是O(log(n))。 HashMap中的put方法执行过…

mysql的增删改查(常用)

增(insert) 语法: insert into 表名(字段) values( 字段对应的值) 案例: 创建一个学生表 结构如下: create table student(id int ,name varchar(20),age int); 向表中插入2条数据 create table student(id int ,n…

小程序--vscode配置

要在vscode里开发微信小程序,需要安装以下两个插件: 安装后,即可使用vscode开发微信小程序。 注:若要实现鼠标悬浮提示,则需新建jsconfig.json文件,并进行配置,即可实现。 jsconfig.json内容如…

linux系统---安装使用nginx

目录 一、编译安装Nginx 1、关闭防火墙,将安装nginx所需要软件包传到/opt目录下 ​编辑2、安装依赖包 3、创建运行用户、组 4、编译安装nginx 5、创建软链接后直接nginx启动 ​编辑 6、创建nginx自启动文件 ​编辑6.1 重新加载配置、设置开机自启并开启服务…

一次奇怪的事故:机器网络连接打满,导致服务不可用

业务背景 发生事故的业务系统是一个toB业务,业务是服务很多中小企业进行某项公共信息指标查询。系统特点:业务处理相对简单,但是流量大,且对请求响应要求较高: 业务请求峰值qps达50w,平时流量达20w左右。 请求响应时…

175基于matlab信号匹配追踪稀疏分解代码

基于matlab信号匹配追踪稀疏分解代码,基于gabor时频原子,对信号重构效果好。输出原子选择过程,重构误差及重构后的信号。程序已调通,可直接运行。 175 匹配追踪稀疏分解 gabor时频原子 (xiaohongshu.com)

申创贝拓电气设备邀您参观2024生物发酵展

参展企业介绍 BETTO贝拓电气成立于2017年,初期总部坐落于安徽合肥,从事工业电控机柜的设计和销售工作。2022年总部迁往上海,有了自己的制造基地,涉及制造和销售工业控制柜、操作台、IT机柜、户外机柜、人机界面、悬臂、电气安装成…

pytest教程-12-fixture作用域

领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了pytest fixture的基本使用方法,本小节我们讲解一下fixture的作用域。 fixture前后置区分 控制fixture的前置和后置操作是通过yield关键字进行来区分的,代码在yield前面…

构建React TodoList应用:管理你的任务清单

构建React TodoList应用:管理你的任务清单 在日常生活和工作中,任务管理是一项至关重要的任务。为了更好地组织和管理我们的工作和生活,我们需要一个高效而简单的任务管理工具。本文将介绍如何使用React框架构建一个功能丰富的TodoList应用&…

如何保证档案室符合建设标准要求

保证档案室符合建设标准要求需要考虑以下几个方面: 1. 总体规划:合理规划档案室的布局和大小,确保能够满足现有和未来的档案存储需求。考虑档案室的空间利用率、通风、照明、安全出口等因素。 2. 档案室环境:档案室的环境应具备稳…

【Android 高德地图POI定位地址搜索】

先上演示: 高德地图的key申请这里就不讲了,比较简单,网上有很多资料,或者前往官网查看:官方文档 依赖引入 项目使用了如下依赖: //高德地图implementation com.amap.api:3dmap:latest.integration//地图…

第六十八天 APP攻防-XposedFridaHook证书校验反代理代理转发

第68天 APP攻防-Xposed&Frida&Hook&证书校验&反代理&代理转发 知识点: 1、APP防代理绕过-应用&转发 2、APP证书校验类型-单向&双向 3、APP证书校验绕过-Frida&XP框架等 章节点: 1、信息收集-应用&资产提取&权…

Elasticsearch 别名(Aliases)的作用

Elasticsearch 8.4.3 别名(Aliases) 一. 介绍二. 别名的优势三. 别名的基本操作3.1 创建别名3.2 查询别名关联的索引3.3 删除别名3.4 更新别名3.5 通过别名查询数据 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接…

【Redis学习笔记03】Java客户端

1. 初识Jedis Jedis的官网地址&#xff1a;https://github.com/redis/jedis 1.1 快速入门 使用步骤&#xff1a; 注意&#xff1a;如果是云服务器用户使用redis需要先配置防火墙&#xff01; 引入maven依赖 <dependencies><!-- 引入Jedis依赖 --><dependency&g…