设计模式之结构型模式---装饰器模式

目录

  • 1.概述
  • 2.类图
  • 3.应用场景及优缺点
    • 3.1 应用场景
    • 3.2 优缺点
      • 3.2.1 优点
      • 3.2.2 缺点
  • 4.实现
    • 4.1 案例类图
    • 4.2 代码实现
      • 4.2.1 定义抽象构建角色
      • 4.2.2 定义具体构建角色
      • 4.2.3 定义抽象装饰器角色
      • 4.2.4 定义具体装饰角色
      • 4.2.5 装饰器模式的使用

1.概述

装饰器模式是指在不改变现有对象结构的情况下,动态的给对象增加一些职责。它是一种用于替代继承的技术,通过一种无需定义子类的方式给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。装饰器模式通过引入一个装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,达到扩展原有功能的目的。例如造一个交通工具,这种交通工具刚开始时只能是在陆地上跑,也就是咱们的汽车,但是随着技术的发展,我们可以给我们的汽车增加在水中移动的功能,或者是在天上飞的功能。这就是装饰器模式的场景之一。后面会用Java语言的代码来实现这个例子。

2.类图

在这里插入图片描述
装饰器模式的主要角色有如下几个:

抽象构建角色(Component): 定义一个抽象接口,规范准备接收附加责任的对象
具体构建角色(ConcreteComponent): 实现抽象构建角色定义的接口。通过装饰器角色为其添加职责
抽象装饰器角色(Decorator) 实现抽象构建中定义的接口,并包含具体构建角色的实例,可以通过其子类扩展具体构建角色实例的功能
具体装饰角色(ConcreteDecorator1、ConcreteDecorator2): 实现抽象装饰的相关方法,并给具体构建角色添加新的职责(功能)

3.应用场景及优缺点

3.1 应用场景

当不能采用继承的方式扩展功能或者是采用继承的方式扩展功能时不好维护的情况下就可以使用装饰器模式。比如一个功能的定义时就有基础版,加强版,VIP版本等基于基础功能扩展出新功能的情况下,我们就可以采用装饰器模式。因为装饰器模式完全遵守开闭原则,即对修改关闭,对扩展开放。

3.2 优缺点

3.2.1 优点

装饰器模式的优点有四个,如下:

  1. 对于扩展对象的功能,装饰器模式比继承更加灵活,因为装饰器模式不会导致类的个数急剧增加。
  2. 使用装饰器模式可以让我们通过一种动态的方式扩展一个对象的功能,比如我们可以通过配置文件在运行的时候选择不同的具体装饰类,从而实现不同的行为
  3. 装饰器可以对一个对象进行多次装饰
  4. 具体构建类与具体装饰类可以独立变化,用户可以更具需要增加的具体构建类和具体装饰类。符合开闭原则

3.2.2 缺点

装饰器模式的缺点主要有两个,如下:

  1. 使用装饰器模式进行系统设计时将会产生很多小对象,大量的小对象会占用更多的系统资源,在一定程度上会影响程序的性能
  2. 装饰器模式使用起来比继承更容易出错,排除错误也会更困难,特别是对于多次装饰的对象,调试时寻找错误可能需要逐级排查。

4.实现

我们以一个汽车改造成水陆两用汽车,陆空两用汽车的例子介绍装饰器模式在程序中的实现,我们用Java语言实现。

假设我们要造一个代步的交通工具,这个交通工具第一版本只需要在陆地上跑就行,也就是我们的汽车,然后随着技术增长,我们需要为我们的汽车扩展在水中行驶的能力和在空中飞行的能力,使用Java代码实现如下所示:

4.1 案例类图

在这里插入图片描述

4.2 代码实现

4.2.1 定义抽象构建角色

首先我们定义一个ITransportation接口,实现我们交通工具的基本能力—移动,这个接口就是我们装饰器模式中的抽线构建角色

public interface ITransportation {void move();
}

4.2.2 定义具体构建角色

定义好抽象构建角色后,我们就可以定义具体构建角色,也就是我们的汽车类了,在汽车类里实现了抽象构建角色定义的功能

public class Car implements ITransportation {public Car(){System.out.println("我只是单纯的一辆车");}@Overridepublic void move() {System.out.println("我可以在陆地上移动");}
}

4.2.3 定义抽象装饰器角色

接下来就需要定义抽象装饰器角色准备扩展功能,为了能扩展汽车的能力,我们提供了一个Transformer类,这个类也实现了抽象构建角色中的ITransportation接口,并且将抽象构建角色对应的具体构建角色通过构造函数注入到Transformer类中,这里的Transformer类就相当于抽象装饰器角色。我们需要的扩展功能后的对象都需要继承它。

public class Transformer implements ITransportation {private final ITransportation mTransportation;public Transformer(ITransportation transportation){this.mTransportation = transportation;}@Overridepublic void move() {mTransportation.move();}
}

4.2.4 定义具体装饰角色

具体装饰角色有两个,分别是水陆两用的汽车AmphibiousCar ,陆空两用的汽车FlyingCar,在这两个具体装饰角色中添加了各自的特色功能。

public class AmphibiousCar extends Transformer{public AmphibiousCar(ITransportation transportation) {super(transportation);System.out.println("我是水陆两用汽车");}public void moveInWater(){System.out.println("我可以在水里跑");}
}
public class FlyingCar extends Transformer{public FlyingCar(ITransportation transportation) {super(transportation);System.out.println("我是陆空两用汽车");}public void flying(){System.out.println("我可以在天上飞");}
}

4.2.5 装饰器模式的使用

使用时我们先通过抽象构建角色创建出具体构建角色的对象,这个对象时需要被装饰的对象,然后将其传递到陆空两用车类的构造函数中和水陆两用车类的构造函数中,分别创建出陆空两用车的对象,水陆两用车的对象。然后调用对应的方法实现各自的能力

public class Client {public static void main(String[] args) {ITransportation myCar = new Car();myCar.move();System.out.println("============================");System.out.println("===========陆空两用车=============");FlyingCar flyingCar = new FlyingCar(myCar);flyingCar.move();flyingCar.flying();System.out.println("=============水陆两用车======================");AmphibiousCar amphibiousCar = new AmphibiousCar(myCar);amphibiousCar.move();amphibiousCar.moveInWater();}
}

运行结果如下所示:

在这里插入图片描述

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

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

相关文章

SQL,力扣题目1709,访问日期之间最大的空档期

一、力扣链接 LeetCode_1709 二、题目描述 表: UserVisits ------------------- | Column Name | Type | ------------------- | user_id | int | | visit_date | date | ------------------- 该表没有主键,它可能有重复的行 该表包含用户访问…

极市平台 | NeurIPS 2024|浙大/微信/清华提出:彻底解决扩散模型反演问题

本文来源公众号“极市平台”,仅用于学术分享,侵权删,干货满满。 原文链接:NeurIPS 2024|浙大/微信/清华提出:彻底解决扩散模型反演问题 极市导读 本文介绍了浙江大学、微信和清华大学联合提出的BELM算法…

心觉:人每日60000念头,如何让你的时间精力只专注于核心目标?

Hi,我是心觉,带你用潜意识化解各种焦虑、内耗,建立无敌自信;教你财富精准显化的实操方法;关注我,伴你一路成长! 每日一省写作220/1000天 据说一个人每天会产生60000个念头 有些我们的意识能察觉到&#x…

89.冒泡算法(代码编写)

目录 一.代码编写 二.视频教程 一.代码编写 #include <stdio.h>void main(void) {int data[10];int j,i;int temp;printf("Please input data:\n");for(i0;i<10;i){scanf("%d",&data[i]);}for(i0;i<10;i){for(j0;j<9-i;j){if(data[j…

SQL CASE表达式与窗口函数

CASE 表达式是一种通用的条件表达式&#xff0c;类似于其他编程语言中的if/else语句。 窗口函数类似于group by&#xff0c;但是不会改变记录行数&#xff0c;能扫描所有行&#xff0c;能对每一行执行聚合计算或其他复杂计算&#xff0c;并把结果填到每一行中。 1 CASE 表达式…

ubuntu22-安装vscode-配置shell命令环境-mac安装

文章目录 1.安装vscode2.修改语言为中文3.配置bash调试环境3.1.安装插件3.2.添加配置文件 4.调试bash4.1.新建tmp.sh文件4.2.运行启动 5.mac安装6.mac卸载 1.安装vscode 从官网下载安装包Code_1.93.1-1726079302_amd64.deb。 在ubuntu系统中&#xff0c;安装包所在目录打开命令…

Chromium127编译指南 Linux篇 - 同步第三方库以及Hooks(六)

引言 在成功克隆 Chromium 源代码仓库并建立新分支之后&#xff0c;配置开发环境成为至关重要的下一步。这一过程涉及获取必要的第三方依赖库以及设置钩子&#xff08;hooks&#xff09;&#xff0c;这些步骤对于确保后续的编译和开发工作能够顺利进行起着决定性作用。本指南旨…

【NOIP提高组】虫食算

【NOIP提高组】虫食算 C语言C &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 所谓虫食算&#xff0c;就是原先的算式中有一部分被虫子啃掉了&#xff0c;需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子&#xff1a; 43#98…

练习LabVIEW第三十题

学习目标&#xff1a; 刚学了LabVIEW&#xff0c;在网上找了些题&#xff0c;练习一下LabVIEW&#xff0c;有不对不好不足的地方欢迎指正&#xff01; 第三十题&#xff1a; 用labview写一个获取当前系统时间的程序 开始编写&#xff1a; 前面板添加一个字符串显示控件&am…

书生大模型实战营 L0 入门岛

书生大模型训练营入门岛任务——训练营链接 1. Linux前置知识 任务&#xff1a;端口转发 当使用vscode远程连接服务器时&#xff0c;在服务器运行的任务&#xff0c;vscode会自动帮忙进行端口映射&#xff0c;方便本地进行访问。 2. Python前置知识 任务1&#xff1a;Leec…

【本科毕业设计】基于单片机的智能家居防火防盗报警系统

基于单片机的智能家居防火防盗报警系统 源码下载摘要Abstract第1章 绪论1.1课题的背景1.2 研究的目的和意义 第2章 系统总体方案设计2.1 设计要求2.2 方案选择和论证2.2.1 单片机的选择2.2.2 显示方案的选择 第3章 系统硬件设计3.1 整体方案设计3.1.1 系统概述3.1.2 系统框图 3…

<项目代码>YOLOv8 猫狗识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

前端项目使用高德地图插件

高德开放平台 | 高德地图API 1、注册成为开发者 登录 高德开放平台控制台&#xff0c;如果没有开发者账号&#xff0c;请 注册开发者。 2. 创建key&#xff0c;项目里面要用 进入应用管理&#xff0c;创建新应用&#xff0c;新应用中添加 key&#xff0c;服务平台选择 Web端…

统信UOS开发环境支持php

UOS对PHP开发环境提供了灵活的选择,在这里开发者可以轻松搭建开发环境,是开发者最理想的选择。 文章目录 一、环境部署php开发环境安装二、代码示例PHP开发案例三、常见问题1. 权限问题2. PHP-FPM服务未正确启动或配置错误一、环境部署 php开发环境安装 php为服务器开发语言…

word转ppt软件哪个好?这些工具你值得拥有

在日常工作和学习中&#xff0c;我们经常需要将word文档转换为ppt幻灯片&#xff0c;以便于展示和汇报。 为了提高效率&#xff0c;市场上涌现了许多word转ppt工具&#xff0c;它们能够自动排版&#xff0c;帮助我们快速完成转换工作。 一、迅捷PPT &#x1f525;优势——多样…

idm扩展自动更新,导致不能正常使用处理方法

idm扩展自动更新&#xff0c;导致不能正常使用处理方法 针对于edge和chrome浏览器的设置 处理思路&#xff0c;设置权限&#xff0c;让浏览器的没有权限修改扩展的文件&#xff0c;从而关闭自动更新 具体做法 1找到idm安装路径&#xff0c;里面有IDMGCE.crx的文件就是扩展文…

Spring框架的声明式事务

目录 一.配置文件的方式 1.配置文件 2.业务层 3.持久层 4.测试类 5.运行 6.查看数据库 7.出现异常运行 二.半注解的方式 1.配置文件 2.db.properties 3.持久层 4.业务层 5.测试类 6.运行 7.查看数据库 8.加上异常 三.纯注解的方式 1.持久层 2.业务层 3.配置…

弹性布局flex-direction

通常来讲&#xff0c;要布局一个底部按钮固定&#xff0c;中间内容可以滑动&#xff0c;都会用中间内容padding-bottom固定内容的高度来使内容可以滑动到看见全部。 如果在固定的内容里&#xff0c;有一个数据为动态&#xff0c;并且可以很多&#xff0c;会导致固定的内容高度不…

spring ai 入门 之 结构化输出 - 把大模型llm返回的内容转换成java bean

目录 ​编辑 将AI非结构化文本转换为特定格式数据的应用场景说明 Spring AI 介绍 &#xff1a;为Java开发者打造的AI应用开发框架 Qwen 介绍 &#xff1a; 一个国内领先的开源大模型 Spring AI Alibaba框架介绍 &#xff1a; 一个国内最好的spring ai实现 使用spring ai …

深入解析:物联网技术及其应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 深入解析&#xff1a;物联网技术及其应用 深入解析&#xff1a;物联网技术及其应用 深入解析&#xff1a;物联网技术及其应用 物…