装饰器模式-原理分析以及动手练习

目录

    • 应用场景
    • 涉及的角色和类(个人理解)
    • 涉及的角色组件(标准)
    • 基本实现 Demo(可以直接 copy 跑一下看效果)
    • 自己动手实战
      • 需求
      • 参考答案
    • 相关话题
    • 参考文章

应用场景

  • 需要给一个现有类添加附加功能,但由于某些原因不能使用继承来生成子类进行扩充时,可以使用装饰模式。
  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时,可以使用装饰模式。

涉及的角色和类(个人理解)

  • 简单来说是两类角色:Source(Component)Decorator,即 被装饰者(原类)装饰者
  • 从类实现分析:
    • 由于 被装饰者装饰者 需要实现同样的方法,需要定义一个抽象接口。
    • 为便于区分,被装饰者抽象接口叫 Component,具体的被装饰者叫 ConcreteComponent
    • 考虑到可能有多个具体的装饰器,需要一个抽象类装饰器叫 Decorator,它的多个具体实现类分别叫 AConcreteDecorator, BConcreteDecorator
      在这里插入图片描述

涉及的角色组件(标准)

  • 被装饰组件接口:Component
  • 具体的被装饰组件实现类:AConcreteComponent, BConcreteComponent
  • 装饰器抽象类:Decorator
  • 具体的被装饰器实现类:AConcreteDecorator, BConcreteDecorator

基本实现 Demo(可以直接 copy 跑一下看效果)

  • Demo,有一个 图形Shape 被装饰接口,有 两个被装饰者的具体实现 Circle, Rectangle,有两个装饰器,分别用来 给图形设置绿色给图形设置红色
  • 在本地创建一个java类 DecoratorTest02,然后 copy 一下代码,直接跑
/*** 装饰器模式要实现的类* Component* AConcreteComponent* BConcreteComponent* Decorator* AConcreteDecorator* BConcreteDecorator*/// 1. 实现 被装饰器组件 操作
// Component
interface Shape {void draw();
}// 2. 实现 被装饰器组件 的具体实现类
// AConcreteComponent
class Circle implements Shape {@Overridepublic void draw() {System.out.println("画一个圆形");}
}// BConcreteComponent
class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("画一个方形");}
}// 3. 实现 装饰器
// Decorator
abstract class Decorator implements Shape {// 使用 protected,便于子类访问protected Shape shape;public Decorator(Shape shape) {this.shape = shape;}@Overridepublic void draw() {shape.draw();}}// 4. 实现 具体功能的 装饰器
// AConcreteDecorator
class RedDecorator extends Decorator {public RedDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {// 可以在原功能之前增加功能// 调用原方法shape.draw();// 可以在原功能之后增加功能setRed(shape);}// 装饰器功能:设置红色public void setRed(Shape shape) {System.out.println("设置红色");}
}// BConcreteDecorator
class GreenDecorator extends Decorator {public GreenDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {shape.draw();setRed(shape);}// 装饰器功能:设置绿色public void setRed(Shape shape) {System.out.println("设置绿色");}
}// 5. 在客户端中使用 装饰器
public class DecoratorTest02 {public static void main(String[] args) {// 1. 标准的使用过程,画一个 圆,红色的// 创建一个 被装饰器组件圆Circle circle = new Circle();// 创建一个 具体的装饰器红色RedDecorator redDecorator = new RedDecorator(circle);// 执行方法redDecorator.draw();// 2. 画一个 方形,红色的new RedDecorator(new Rectangle()).draw();// 3. 画一个 方形,绿色的new GreenDecorator(new Rectangle()).draw();// 总结 可以看出,使用装饰器,可以对原来的类 动态添加、删除装饰功能}
}

自己动手实战

需求

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

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

要求:可以制作 加牛奶的黑咖啡,加糖的黑咖啡,加糖的拿铁咖啡

原练习题链接

参考答案

// Component: 被装饰者接口
interface Coffee {void createCoffee();
}// AConcreteComponent: 被装饰者的具体实现类 黑咖啡
class BlackCoffee implements Coffee {@Overridepublic void createCoffee() {System.out.println("create black coffee");}
}// BConcreteComponent: 被装饰者的具体实现类 拿铁咖啡
class Latte implements Coffee {@Overridepublic void createCoffee() {System.out.println("create latte coffee");}
}// Decorator: 装饰器抽象类
abstract class Decorator implements Coffee {// 让子类可以访问到 被装饰者protected Coffee coffee;public Decorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic void createCoffee() {coffee.createCoffee();}
}// AConcreteDecorator: 装饰器具体实现类 加牛奶装饰
class MilkDecorator extends Decorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic void createCoffee() {// 在原方法之前 做装饰washCup();// 执行原方法coffee.createCoffee();// 在原方法之后做装饰addMilk(coffee);}// 装饰功能:洗杯子public void washCup() {System.out.println("洗杯子");}// 装饰功能:加牛奶public void addMilk(Coffee coffee) {System.out.println("加入牛奶");}
}// BConcreteDecorator: 装饰器具体实现类 加糖装饰
class SugarDecorator extends Decorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic void createCoffee() {coffee.createCoffee();addSugar(coffee);}public void addSugar(Coffee coffee) {System.out.println("加入一些糖");}
}public class DecoratorTest01 {public static void main(String[] args) {BlackCoffee blackCoffee = new BlackCoffee();SugarDecorator sugarDecorator = new SugarDecorator(blackCoffee);sugarDecorator.createCoffee();}
}

相关话题

  • Java IO 流中如何应用的装饰器模式
  • 什么时候可以考虑使用装饰器模式
  • 能徒手写一个装饰器模式的demo吗

参考文章

  • https://github.com/youngyangyang04/kama-DesignPattern/blob/main/DesignPattern/8-%E8%A3%85%E9%A5%B0%E6%A8%A1%E5%BC%8F.md
  • https://www.runoob.com/design-pattern/decorator-pattern.html
  • https://pdai.tech/md/java/io/java-io-basic-design-pattern.html
  • https://kamacoder.com/problempage.php?pid=1086

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

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

相关文章

Nginx+GateWay

目录 Nginx nginx如何配置负载均衡 负载均衡有哪些策略 1、轮询(默认) 2、指定权重 3、ip_hash(客户端ip绑定) 4、least_conn(最少连接) 5、fair 6、url_hash Nginx为什么效率高 gateway 使用gat…

学习云计算亚马逊云科技AWS的6大教科书神级别免费网站

亚马逊☁️(AWS)是全球云行业最🔥火云平台,云行业的就业机会和市场前景都非常巨大,现在通过学AWS去转云会是个千载难逢的好机会。小李哥这次来盘点学习AWS的6大教科书级免费官方网站(免费课程+动手实验)。欢迎大家点击图片左下角加…

QT:label标签/进度条的使用

文章目录 设置不同格式的文本显示图片文本对齐/自动换行/缩进/边距LCDNumber倒计时 ProgressBar进度条 设置不同格式的文本 在文本格式中,存在富文本,makedown格式的文本,还有纯文本,下面就依据这三个进行举例 #include "w…

领鸡蛋游戏养鸡游戏淘宝客源码广告联盟功能介绍

领鸡蛋游戏功能介绍 核心功能 用户鸡蛋数量 玩家在游戏中会累积一定数量的鸡蛋,这些鸡蛋可以通过完成任务、签到、邀请好友等方式获得。鸡蛋数量直接关联到玩家的游戏进度和奖励。足迹 足迹功能展示用户的饲料明细,包括饲料的获取方式、数量以及时间等…

公司数据防泄漏方案分享|防泄密软件有哪些

企业的数据安全是公司稳定发展的必要条件,如何防止内部数据泄露企业的数据安全是公司稳定发展的必要条件,如何防止内部数据泄露已经成为了一个亟待解决的问题。在这个信息时代,数据已经成为企业最重要的资产之一,因此,…

AWS宣布推出Amazon Q :针对商业数据和软件开发的生成性AI助手

亚马逊网络服务(AWS)近日宣布推出了一项名为“Amazon Q”的新服务,旨在帮助企业利用生成性人工智能(AI)技术,优化工作流程和提升业务效率。这一创新平台的推出,标志着企业工作方式的又一次重大变…

机械类外文 翻译

随着科技的日新月异,机械工程领域也在不断蜕变,为了更好地与世界接轨,对外文资料的准确翻译显得尤为重要。那么,那么,关于机械类的外文翻译,如何保证译文的质量,哪个翻译公司在北京更为专业呢&a…

密码学《图解密码技术》 记录学习 第十五章

目录 十五章 15.1本章学习的内容 15.2 密码技术小结 15.2.1 密码学家的工具箱 15.2.2 密码与认证 15.2.3 密码技术的框架化 15.2.4 密码技术与压缩技术 15.3 虚拟货币——比特币 15.3.1 什么是比特币 15.3.2 P2P 网络 15.3.3地址 15.3.4 钱包 15.3.5 区块链 15.3.…

安装Nox夜神模拟器关闭了HyperV后Docker运行不了怎么办?

1.背景 为了模拟真机,尝试安装了Nox夜神模拟器, 安装过程要求关闭Hyper-V。当时只是在程序安装卸载中关闭了系统服务。以为到时勾选上就好了。操作路径:控制面板\所有控制面板项\程序和功能\启用或关闭Windows功能\Hyper-V。 后来卸载掉了夜神…

【一起深度学习——NIN】

NIN神经网络 原理图:代码实现:输出结果: 原理图: 代码实现: import torch from torch import nn from d2l import torch as d2ldef nin_block(in_channels, out_channels, kernel_size, strides, padding):return nn.…

零基础自学网络安全/Web安全(超详细入门到进阶)学完即可就业(含学习笔记)

一、为什么选择网络安全? 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地,网络安全行业地位、薪资随之水涨船高。 未来3-5年,是安全行业的黄金发展期,提前踏入…

深度学习之基于Matlab特征匹配的手写电话号码、数字识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在信息化日益发展的今天,手写电话号码和数字的识别技术显得尤为重要。这种技术不仅能够提…

绝地求生:PUBG杜卡迪联名进入倒计时3天!

大家好,我是闲游盒。 杜卡迪联名已经进入倒计时3天!喜欢的朋友要注意结束时间可千万别错过! 杜卡迪6色车辆 随着五一小长假的结束,本次混沌漫彩通行证也即将结束,本次通行证31级之后没升1级可额外领取1500BP和挑战者纪…

【Stream 流】通过一个例子看遍所有Stream API使用场景

前言 上篇文章记录了方法引用,Lambda表达式等基础的知识点,这篇文章主要结合课设项目详细介绍Stream 流的API以及它的主要场景。 Stream API作用 在Java 8及其以后的版本中,Stream API为处理集合数据提供了强大而灵活的功能。有了Stream AP…

普乐蛙元宇宙VR体验馆设备集体亮相VR文旅景区展

普乐蛙全国巡展又双叒叕开始了! 这次来到的是“好客山东”↓↓ 山东2024休闲旅游产业展 4月25日至27日,2024休闲旅游产业展在临沂国际博览中心举办。本次展会以“潮购文旅好品,乐享时尚生活”为主题,汇聚全国文旅产业上下游500多家企业、上万…

武汉理工大学python123实验——流程控制结构

1.百分制成绩转换五分制#1707 n int(input())if n>90:print(A) elif n>80:print(B) elif n>70:print(C) elif n>60:print(D) else:print(E) 2.角古猜想#73963 n eval(input()) if n<0:print(ERROR) elif . in str(n):print(ERROR) else:print(n,end" …

idea无法识别加载pom.xml文件

有时idea无法识别加载pom.xml文件&#xff0c;直接打开pom.xml文件&#xff0c;然后添加到maven就行

新品宣传如何做好网络媒体推广+

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 新品宣传在网络媒体推广中&#xff0c;可以按照以下步骤进行&#xff1a; 产品预热 目标&#xff1a;提高潜在顾客的期待感和好奇心。 方法&#xff1a; A.发布软文&#xff1a;在各大平…

平滑 3d 坐标

3d平滑 import torch import torch.nn.functional as F import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3Dclass SmoothOperator:def smooth(self, vertices):# 使用一维平均池化进行平滑vertices_smooth F.avg_pool1d(vertices.p…

如何开发自己的深度学习优化算法

深度学习优化算法 如何开发自己的深度学习优化算法理解优化算法的基础**核心组件**&#xff1a; 设计自定义优化算法的步骤**步骤 1: 定义问题和目标****步骤 2: 研究现有算法****步骤 3: 开发初步想法****步骤 4: 创建原型****步骤 5: 系统测试与优化** 关键建议 如何开发自己…