笨蛋学设计模式结构型模式-装饰者模式【9】

结构型模式-装饰者模式

    • 7.3装饰者模式:arrow_up::arrow_up::arrow_up:
      • 7.3.1概念
      • 7.3.2场景
      • 7.3.3优势 / 劣势
      • 7.3.4装饰者模式可分为
      • 7.3.5装饰者模式
      • 7.3.6实战
        • 7.3.6.1题目描述
        • 7.3.6.2输入描述
        • 7.3.6.3输出描述
        • 7.3.6.4代码
      • 7.3.7总结
      • 装饰者模式

7.3装饰者模式⬆️⬆️⬆️

7.3.1概念

​ 装饰者模式通过在一个现有对象中,能动态的给该对象添加新的功能,同时不改变对象本身的结构,是继承的一种替代方案,可以实现在不定义子类的情况下,运行时动态地扩展对象的行为(给对象添加一些额外的功能),而无需修改原有代码。

7.3.2场景

​ 当我们去一家咖啡店时,点了一杯咖啡。这时,你觉得咖啡有点苦,或者说咖啡的味道不够丰富,就可以给店员 / 咖啡师说,希望可以在我们的咖啡中添加糖、牛奶等不同的食材以此来丰富我们咖啡。这些食物都可以看作是装饰者,然后我们可以根据自己的具体口味,添加不同程度的以及不同风味的食材。

7.3.3优势 / 劣势

  • 可扩展性:根据多个不同的装饰类来组合出不同功能,以此来装饰同一对象
  • 灵活性:在不改变原有对象的基础上,动态的给对象添加新的功能
  • 易于维护:由于装饰者模式的动态性,可以随时添加或删除装饰者,无需修改原有的代码

  • 系统复杂度:因为装饰者模式需要创建更多的类和对象,会增加系统的复杂度
  • 执行效率降低:装饰者模式是动态添加 / 删除的,可能会引入一些性能问题,最后导致执行效率降低

7.3.4装饰者模式可分为

  • 组件Component:通常是抽象类或者接口,是具体组件和装饰者的父类,定义了具体组件需要实现的方法
  • 具体组件ConcreteComponent:实现类Component接口的具体类,是被装饰的对象
  • 装饰类:一个抽象类,给具体组件添加功能,但是具体的功能由其子类具体装饰者完成,持有一个指向Component对象的引用
  • 具体装饰类ConcreteDecorator:扩展Decorator类,负责向Component对象添加新的行为,加牛奶的咖啡是一个具体装饰类,加糖的咖啡也是一个具体装饰类

7.3.5装饰者模式

package com.technologystatck.designpattern.mode.decoration;public class Decoration {public static void main(String[] args) {//创建具体组件ConcreteComponent concreteComponent = new ConcreteComponent();//使用具体装饰者装饰具体组件Decorator decorator = new ConcreteDecorator(concreteComponent);//调用方法decorator.operation();}
}//1.定义Component组件接口
interface Component{void operation();
}//2.实现ConcreteComponent具体组件
class ConcreteComponent implements Component{@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}//3.定义抽象Decorator装饰类,继承自Component
abstract class Decorator implements Component{protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}//4.定义具体的装饰者实现,给具体组件对象添加功能
class ConcreteDecorator extends Decorator{public ConcreteDecorator(Component component) {super(component);}@Overridepublic void operation() {System.out.println("Before operation in ConcreteDecorator");super.operation();System.out.println("After operation in ConcreteDecorator");}
}

7.3.6实战

7.3.6.1题目描述

小明喜欢品尝不同口味的咖啡,他发现每种咖啡都可以加入不同的调料,比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。

请设计一个简单的咖啡制作系统,使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型:黑咖啡(Black Coffee)和拿铁(Latte)。

7.3.6.2输入描述

多行输入,每行包含两个数字。第一个数字表示咖啡的选择(1 表示黑咖啡,2 表示拿铁),第二个数字表示要添加的调料类型(1 表示牛奶,2 表示糖)。

7.3.6.3输出描述

根据每行输入,输出制作咖啡的过程,包括咖啡类型和添加的调料。

7.3.6.4代码
package com.technologystatck.designpattern.mode.decoration;import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while(scanner.hasNext()){//咖啡类型int coffeeType = scanner.nextInt();//咖啡装饰类型int condimentType = scanner.nextInt();//根据选择制作不同的咖啡Coffee coffee=null;if(coffeeType ==1){coffee=new BlackCoffee();}else if(coffeeType ==2){coffee=new Latte();}else{System.out.println("Invald coffee type");continue;}//添加不同的食材if(condimentType == 1){coffee=new MilkDecorator(coffee);}else if(condimentType ==2){coffee=new SugarDecorator(coffee);}else{System.out.println("Invald condiment type");continue;}//输出制作过程coffee.brew();}}
}//抽象咖啡组件
interface Coffee{//制作咖啡的方法void brew();
}//具体的黑咖啡类
class BlackCoffee implements Coffee{@Overridepublic void brew() {System.out.println("Brewing Black Coffee");}
}//具体的拿铁咖啡类
class Latte implements Coffee{@Overridepublic void brew() {System.out.println("Brewing Latte Coffee");}
}//装饰者抽象类
abstract class AbstractDecorator implements Coffee{protected Coffee coffee;public AbstractDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic void brew() {coffee.brew();}
}//具体的牛奶装饰者类实现
class MilkDecorator extends AbstractDecorator{public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic void brew() {super.brew();System.out.println("Adding Milk");}
}class SugarDecorator extends AbstractDecorator{public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic void brew() {super.brew();System.out.println("Adding Sugar");}
}

7.3.7总结

  • 装饰者模式

  • 优点:是一种比继承更弹性的替代方案,不改变原有代码,动态添加新功能

  • 总结:若需要动态地扩展对象的功能,不会过度复杂化系统代码,可以选择装饰者模式

  • 场景

    • 由于某些原因不能使用继承来生成子类进行扩充时
    • 当对象的要求可以动态地添加,也可以动态地删除时

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

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

相关文章

【PWN · GOT表劫持 | 整数溢出】[HGAME 2023 week1]choose_the_seat

整数溢出,加之保护开的不全,可以反复越界修改got表,劫持puts函数实现利用 一、题目概述 限制:v0不可以大于9 理想中数组所在bss端地址: 注意到与got表项距离很近 危险函数只能执行一遍,然后回exit(0) 二…

Next.js 开发指​南(GitHub 115k star​)

Next.js 是一个构建于 Node.js 之上的开源 Web 开发框架,它扩展了最新的 React 特性,集成了基于 Rust 的 JavaScript 工具,可以帮助你快速创建全栈 Web 应用 (full-stack Web applications) 。 对于有一定 React 基础…

华为数通方向HCIP-DataCom H12-831题库(判断题:21-40)

第21题 OSPF的NSSA区域内,在ASBR路由器上不论路由表中是否存在缺省路由,都会自动产生描述缺省路由的Type7LSA,通告到整个NSSA区域 正确 错误 答案:错误 解析: 在NSSA区域中,ASBR默认情况下不会产生7类LSA表示的默认路由。 第22题 BFD单跳检测是指对两个直连接口进行IP连…

Express安装与基础使用

一、express 介绍 express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架, 官方网站: Express - 基于 Node.js 平台的 web 应用开发框架 - Express中文文档 | Express中文网 中文文档: 路由 - Express 中文文档 简单来说&am…

数据库概念大全

1.数据库的四个基本概念 (1)数据 data:描述事物的符号,数据库中存储的基本对象。 (2)数据库 DataBase, DB:长期存储在计算机内的,有组织的,可共享的大量数据集合、 (3)数据库管理系统 DMBS:位于用户与操作系统之间的一层数据管…

Kafka生产消费流程

Kafka生产消费流程 1.Kafka一条消息发送和消费的流程图(非集群) 2.三种发送方式 准备工作 创建maven工程&#xff0c;引入依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.3.1…

笔试面试题——继承和多态

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、什么是多态&#xff1f;二、什么是重载、重写(覆盖)、重定义(隐藏)&#xff1f;三、 inli…

实现将信息作为txt,pdf,图片的形式保存到电脑~

PrintableUtils作为输出信息的工具类&#xff1a; package org.example; import com.itextpdf.text.*; import com.itextpdf.text.Font; import com.itextpdf.text.pdf.PdfWriter; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; im…

QT发布成exe不能运行解决方案

原因 qt发布成exe后不会把依赖的dll自动拷贝到文件夹中. 解决方案&#xff1a; 输入&#xff1a;windeployqt 拖拉 生产的exe到命令行. 会自动copy依赖到文件夹中&#xff1a; 然后就可以单击运行了&#xff01;

【温故而知新】HTML5的Video/Audio

文章目录 一、概念二、Video浏览器支持视频格式视频标签 三、Audio浏览器支持音频格式标签 一、概念 HTML5是HTML的最新版本&#xff0c;它引入了许多新的元素和功能&#xff0c;以适应现代网页开发的需求。以下是HTML5的一些主要特点&#xff1a; 新增语义元素&#xff1a;H…

电路原理1-线性电阻

前言&#xff1a;整理笔记基于清华大学于歆杰老师的《电路原理》&#xff0c;电路原理是基于无源负载和电源组成电路的分析方法。 1.基础数学知识 算术&#xff1a;数字之间的运算 代数&#xff1a;用变量和函数来代替数字 微积分&#xff1a;描述函数的累积效应&#xff0…

贝叶斯方法家族

贝叶斯方法 机器学习框架贝叶斯方法贝叶斯和其他推断方法的区别朴素贝叶斯分类五个 NB 分类器 贝叶斯推断马尔科夫-蒙特卡洛方法变分推断隐马尔科夫模型 贝叶斯网络贝叶斯置信网络 贝叶斯深度学习贝叶斯神经网络贝叶斯卷积神经网络贝叶斯图神经网络贝叶斯优化方法 机器学习框架…

Golang 三数之和+ 四数之和 leetcode15、18 双指针法

文章目录 三数之和 leetcode15map记录 失败&#xff01;超出限制双指针法 四数之和 leetcode18 三数之和 leetcode15 知识补充&#xff1a; map的key值必须是可以比较运算的类型&#xff0c;不可以是函数、map、slice map记录 失败&#xff01;超出限制 //得到结果后再去重 失…

shell简单截取curl GET返回的body消息体

目录 需求背景&#xff1a; 示例&#xff1a; 解决方式&#xff1a; 需求背景&#xff1a; 用shell解析 curl命令GET到的消息体&#xff0c;获取body消息体里的某个字段的值,只是个简单的示例&#xff0c;可以在此基础上更改满足自己的需求 示例&#xff1a; curl一个API…

纳米软件射频测试系统助力放大器静态参数测试

放大器是可以把输入讯号的电压或功率放大&#xff0c;增加信号幅度的一种装置&#xff0c;可以提高信号质量、增加功率、提高灵敏度等&#xff0c;被应用于通讯、广播、雷达、电视、自动控制等领域。对放大器进行测试是为了确保放大器的性能和稳定性&#xff0c;以保证其可以正…

【Linux】nc 网络诊断 | 文件传输 命令详解

目录 一、命令简介 二、命令使用 2.1 测试服务器 2.2 端口连通性测试 2.2.1tcp端口连通性测试 2.2.2udp端口连通性测试 2.3 文件及目录的传输 2.3.1 文件传输(TCP端口) 2.3.2 文件传输(UDP端口) 相关文章&#xff1a; 【网络】抓包工具Wireshark下载安装和基本使用教…

SpringBoot参数校验@Validated、@Valid

SpringBoot参数校验Validated、Valid&#xff08;javax.validation&#xff09; 一、应用场景 在实际开发中&#xff0c;前端校验并不安全&#xff0c;任何人都可以通过接口来调用我们的服务&#xff0c;就算加了一层token的校验&#xff0c;有心人总会转空子&#xff0c;来传…

华为OD机试真题-最小矩阵宽度-2023年OD统一考试(C卷)

题目描述: 给定一个矩阵,包含N*M个整数,和一个包含K个整数的数组。 现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数。 输入描述: 第一行输入两个正整数N,M,表示矩阵大小。 接下来N行M列表示矩阵内容。 下一行包含一个正整数K。 下一行包含…

51-JS鼠标,键盘,表单,粘贴板,窗口事件,遍历节点树,DOM操作:创建/添加,删除,替换

1.鼠标事件 1.1双击事件dblclick <button>按钮</button><script>var btn = document.getElementsByTagName("button");// 鼠标快速点击两下// 双击dblclickbtn.ondblclick=function(){console.log("aa");}</script> 1.2鼠标移入…

Linux下安装jdk、tomcat

linux下安装jdk、tomcat 一、linux下安装jdk1.1.下载Linux版本的JDK1.2.Linux安装JDk1.3.设置环境变量1.4.卸载JDK 二、linux下安装tomcat2.1.下载Linux版本的Tomcat2.2.在usr目录下新建tomcat目录2.3.进入到tomcat目录中解压下载的tomcat安装包2.4.配置环境变量-前提是已经安装…