23种设计模式之一— — — —装饰模式详细介绍与讲解

装饰模式详细讲解

  • 一、定义
  • 二、装饰模式结构
      • 核心思想
      • 模式角色
      • 模式的UML类图
      • 应用场景
      • 模式优点
      • 模式缺点
  • 实例演示
      • 图示
      • 代码演示
      • 运行结果

一、定义

装饰模式(别名:包装器)
装饰模式(Decorator Pattern)是结构型的设计模式,它允许在运行时动态地向对象添加新的职责或功能,同时保持对象的原始类不变。通过使用装饰器模式,可以在不修改现有代码的基础上扩展对象的功能,

二、装饰模式结构

核心思想

1.动态扩展:在不改变原类结构和继承关系的情况下,动态地为对象添加功能。
2.包装对象:通过创建一个包装对象(装饰器)来包裹真实对象,增加额外功能。
3.接口一致性:装饰器与真实对象有相同的接口,确保客户端能以相同的方式与两者交互。
4.开闭原则:对扩展开放,对修改关闭。新的功能通过添加装饰器实现,而不是修改原类。
5.灵活组合:允许通过组合多个装饰器来创建功能更为丰富的对象

模式角色

1.抽象组件(Component):定义一个接口,用于规范准备接收附加责任的对象(即被装饰对象)。
2.具体组件(ConcreteComponent):实现抽象组件接口,是装饰器要装饰的真实对象。
3.装饰器(Decorator):持有一个抽象组件的引用,并继承抽象组件的接口。它既可以使用所持有的引用调用被装饰的组件的方法,也可以增加新的功能。
4.具体装饰器(ConcreteDecorator):实现装饰器接口并给具体组件添加职责。它通常包含对具体组件的引用,以及一个或多个用于增加功能的额外方法。
这些角色在装饰模式中的交互方式是:

  • 抽象组件定义了所有装饰器对象和被装饰对象需要实现的接口。
  • 具体组件实现了抽象组件接口,是准备被装饰的对象。
  • 装饰器持有一个对抽象组件的引用,并且实现了抽象组件接口。它可以使用这个引用来调用被装饰对象的方法,并在调用前后添加新的功能。
  • 具体装饰器实现了装饰器接口,并且给具体组件添加新的职责。它通常包含一个指向被装饰对象的引用,以及用于实现附加功能的代码。

模式的UML类图

在这里插入图片描述

应用场景

  • 当需要为单个对象提供多种不同的行为或者表现形式时。
  • 需要向一个已经存在的类中添加功能,但又不希望修改该类的源代码或继承其子类时
  • 组合对象:当需要组合多个对象来创建一个具有更多功能的对象时,装饰模式是一个很好的选择。通过递归组合方式,可以构建出一个具有多种功能的对象。例如,在文件系统中,文件夹可以被视为一个特殊的文件,它可以包含其他文件和文件夹。使用装饰模式,可以将文件夹装饰为一个包含额外功能的对象,如支持加密、压缩等

模式优点

  • 动态地给对象添加功能,相比生成子类更加灵活、透明。
  • 无需修改原有类就可以扩展功能,符合开闭原则。
  • 装饰器可以被组合,以便在运行时动态地、多次地添加多个职责。

模式缺点

  • 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
  • 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
  • 不易调试:由于装饰器模式涉及到多个对象的交互,调试可能会变得相对困难。特别是当装饰器链很长时,追踪请求和响应的路径可能会变得复杂。

实例演示

图示

鸡腿堡应用:
在这里插入图片描述

代码演示

package ZhuangShiMoShi;public abstract class Humburger {protected String name;public String getName() {return name;}public abstract double getPrice();}package ZhuangShiMoShi;public class ChickenBurger extends Humburger {public ChickenBurger(){name="鸡腿堡";}public double getPrice(){return 10;}}package ZhuangShiMoShi;public abstract class Condiment extends Humburger {protected Humburger humburger;public abstract String getName();}package ZhuangShiMoShi;public class Chilli extends Condiment {public Humburger hum;public Chilli(Humburger hum) {this.hum = hum;}@Overridepublic String getName() {// TODO Auto-generated method stubreturn hum.getName() + " 加辣椒";}@Overridepublic double getPrice() {// TODO Auto-generated method stubreturn hum.getPrice();}}package ZhuangShiMoShi;public class Lettuce extends Condiment {public Humburger hum;public Lettuce(Humburger hum) {this.hum = hum;}@Overridepublic String getName() {// TODO Auto-generated method stubreturn hum.getName()+" 加生菜";}@Overridepublic double getPrice() {// TODO Auto-generated method stubreturn hum.getPrice()+1.5;}}

测试类:

package ZhuangShiMoShi;public class Test {public static void main(String[] args) {Humburger hum = new ChickenBurger();System.out.println(hum.getName() + " 价钱:" + hum.getPrice());Lettuce lettuce=new Lettuce(hum);System.out.println(lettuce.getName()+" 价钱:"+lettuce.getPrice());Chilli chilli1=new Chilli(hum);System.out.println(chilli1.getName()+" 价钱:"+chilli1.getPrice());Chilli chilli2=new Chilli(lettuce);System.out.println(chilli2.getName()+" 价钱:"+chilli2.getPrice());}}

运行结果

在这里插入图片描述

该代码主体是鸡腿堡,可以选择通过添加生菜、酱、辣椒等等许多其他的配料,并根据选择的配料计算相应的价格。
博主用心写,读者点关注;互动传真情,知识不迷路

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

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

相关文章

U盘无法打开?数据恢复与预防措施全解析

在日常生活和工作中,U盘已成为我们存储和传输数据的重要工具。然而,有时我们会遇到U盘无法打开的情况,这无疑给我们带来了诸多不便。本文将深入探讨U盘打不开的现象、原因及解决方案,并分享如何预防此类问题的发生。 一、U盘无法访…

软件架构设计属性之三:结构性属性浅析

文章目录 引言一、结构性属性的定义二、结构性属性的关键要素1. 组件化2. 模块化3. 层次化4. 接口定义5. 数据流6. 依赖管理 三、结构性属性的设计原则1. 高内聚低耦合2. 松耦合3. 清晰的接口4. 可维护性5. 可扩展性 四、结构性属性的实现策略1. 组件划分2. 模块化设计3. 接口设…

数据结构(1):线性表

1 线性表的顺序实现 创建的新项目是cpp类型哦&#xff01; 1.1 初始化 1.1.1 静态分配 #define _CRT_SECURE_NO_WARNINGS#include <stdio.h> #define MaxSize 10 //定义顺序表的长度 typedef struct {int data[MaxSize];//用静态的数组存放元素&#xff01;int lengt…

目标检测 | R-CNN、Fast R-CNN与Faster R-CNN理论讲解

☀️教程&#xff1a;霹雳吧啦Wz ☀️链接&#xff1a;https://www.bilibili.com/video/BV1af4y1m7iL?p1&vd_sourcec7e390079ff3e10b79e23fb333bea49d 一、R-CNN R-CNN&#xff08;Region with CNN feature&#xff09;是由Ross Girshick在2014年提出的&#xff0c;在PAS…

基于文本来推荐相似酒店

基于文本来推荐相似酒店 查看数据集基本信息 import pandas as pd import numpy as np from nltk.corpus import stopwords from sklearn.metrics.pairwise import linear_kernel from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extrac…

蓝桥杯-AB路线(详细原创)

问题描述&#xff1a; 有一个由 N M 个方格组成的迷宫&#xff0c;每个方格写有一个字母 A 或者 B。小蓝站在迷宫左上角的方格&#xff0c;目标是走到右下角的方格。他每一步可以移动到上下左右相邻的方格去。 由于特殊的原因&#xff0c;小蓝的路线必须先走 K 个 A 格子、再…

java高级——Collection集合之List探索(包含ArrayList、LinkedList、Vector底层实现及区别,非常详细哦)

java高级——Collection集合之List探索 前情提要文章介绍提前了解的知识点1. 数组2. 单向链表3. 双向链表4. 为什么单向链表使用的较多5. 线程安全和线程不安全的概念 ArrayList介绍1. 继承结构解析1.1 三个标志性接口1.2 AbstractList和AbstractCollection 2. ArrayList底层代…

刷爆leetcode第六期

题目一 用队列实现栈 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。 int pop() 移除…

MVC架构中的servlet层重定向404小坑

servlet层中的UserLoginServlet.java package com.mhys.servlet; /*** ClassName: ${NAME}* Description:** Author 数开_11* Create 2024-05-29 20:32* Version 1.0*/import com.mhys.pojo.User; import com.mhys.service.UserService; import com.mhys.service.impl.UserSer…

Paddle使用问题No module named ‘paddle.fluid’

这是Paddle版本的问题&#xff0c;从飞桨框架 2.5 版本开始&#xff0c;已经废弃了 paddle.fluid 。 ​解决方案&#xff1a;修改paddle版本 pip install paddlepaddle2.4.0

2.1色彩空间

色彩发送器 色彩认知 光源是出生点&#xff0c;光源发射出光线&#xff0c;光线通过直射反射折射等路径最终进入人眼。 但人眼接收到光线后&#xff0c;人眼的细胞产生了一系列化学反应。 由此把产生的信号传入大脑&#xff0c;最终大脑对颜色产生了认知感知。 光的要素 光…

汽车IVI中控开发入门及进阶(二十一):DAB和FM 收音机

前言: 在过去的十年里,数字收音机对车载娱乐产生了重大影响。现在,几乎每辆新车都标配了这项技术,这也是我们60%以上的人收听收音机的方式。甚至有传言称,在不久的将来,将永久关闭调频发射机,使许多车载收音机过时。但一些相对年轻的汽车在工厂里仍然没有安装DAB,而且…

UG NX二次开发(C#)-UFun函数-利用UFPart.Export导出模型中的对象并创建一个新的part

文章目录 1、前言2、UF_PART_export函数定义3、UF_PART_export_with_options函数定义4、代码1、前言 在UG NX 10.0二次开发中,需要用到将装配体中通过几何建模创建的对象独立创建一个part文件,所以查找了下UFun函数,即是UF_PART_export 和UF_PART_export_with_options两个函…

J.搬砖【蓝桥杯】/01背包+贪心

搬砖 01背包贪心 思路&#xff1a;要让重量更小的在更前面&#xff0c;价值更大的在更后面&#xff0c;vi−wj>vj−wi viwi>vjwj 第 i 个箱子放在第 j 个箱子下面就显然更优。所以进行排序再用01背包即可。 #include<iostream> #include<algorithm> #defi…

洗地机哪个牌子最好用?十大名牌洗地机排行榜

作为一种新兴的智能家居产品&#xff0c;洗地机的市场规模已经突破了百亿大关。如此庞大的市场自然吸引了大量资本的涌入&#xff0c;许多品牌纷纷推出自己的洗地机产品&#xff0c;试图在这个竞争激烈的市场中占据一席之地。然而&#xff0c;面对如此多的品牌和型号&#xff0…

检索字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了很多应用于字符串查找的方法&#xff0c;这里主要介绍以下几种方法。 &#xff08;1&#xff09;count()方…

JRT性能演示

演示视频 君生我未生&#xff0c;我生君已老&#xff0c;这里是java信创频道JRT&#xff0c;真信创-不糊弄。 基础架构决定上层建筑&#xff0c;和给有些品种的植物种植一样&#xff0c;品种不对&#xff0c;施肥浇水再多&#xff0c;也是不可能长成参天大树的。JRT吸收了各方…

FFMPEG+ANativeWinodow渲染播放视频

前言 学习音视频开发&#xff0c;入门基本都得学FFMPEG&#xff0c;按照目前互联网上流传的学习路线&#xff0c;FFMPEGANativeWinodow渲染播放视频属于是第一关卡的Boss&#xff0c;简单但是关键。这几天写了个简单的demo&#xff0c;可以比较稳定进行渲染播放&#xff0c;便…

vue3 使用vant

使用前提&#xff1a; vite创建的vue3项目 vanthttps://vant-ui.github.io/vant/#/zh-CN/home npm i vant 引入样式&#xff1a; main.js import vant/lib/index.css vant封装 import { showLoadingToast,closeToast,showDialog,showConfirmDialog } from vant;export func…

分布式版本控制工具 git

git 是什么 分布式版本控制工具。github 是代码托管平台。 git 有什么用 保存文件的所有修改记录。使用版本号&#xff08;sha1 哈希值&#xff09; 进行区分。随时可浏览历史版本记录。可还原到历史指定版本。对比不同版本的文件差异。 为什么要使用 git 多人协作开发一个大…