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

目录

    • 应用场景
    • 涉及的角色和类(个人理解)
    • 涉及的角色组件(标准)
    • 基本实现 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 {
    @Override
    public void draw() {
        System.out.println("画一个圆形");
    }
}

// BConcreteComponent
class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个方形");
    }
}

// 3. 实现 装饰器
// Decorator
abstract class Decorator implements Shape {
    // 使用 protected,便于子类访问
    protected Shape shape;

    public Decorator(Shape shape) {
        this.shape = shape;
    }

    @Override
    public void draw() {
        shape.draw();
    }

}

// 4. 实现 具体功能的 装饰器
// AConcreteDecorator
class RedDecorator extends Decorator {

    public RedDecorator(Shape shape) {
        super(shape);
    }

    @Override
    public 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);
    }

    @Override
    public 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();

        // 4. 画一个 方形,红绿色的(可以组合多个装饰功能)
        new RedDecorator(new GreenDecorator(new Rectangle())).draw();

        // 总结 可以看出,使用装饰器,可以对原来的类 动态添加、删除装饰功能
    }
}

自己动手实战

需求

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

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

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

原练习题链接

参考答案

// Component: 被装饰者接口
interface Coffee {
    void createCoffee();
}

// AConcreteComponent: 被装饰者的具体实现类 黑咖啡
class BlackCoffee implements Coffee {
    @Override
    public void createCoffee() {
        System.out.println("create black coffee");
    }
}

// BConcreteComponent: 被装饰者的具体实现类 拿铁咖啡
class Latte implements Coffee {
    @Override
    public void createCoffee() {
        System.out.println("create latte coffee");
    }
}


// Decorator: 装饰器抽象类
abstract class Decorator implements Coffee {
    // 让子类可以访问到 被装饰者
    protected Coffee coffee;

    public Decorator(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public void createCoffee() {
        coffee.createCoffee();
    }
}

// AConcreteDecorator: 装饰器具体实现类 加牛奶装饰
class MilkDecorator extends Decorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public 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);
    }

    @Override
    public 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

北京车展现场体验商汤DriveAGI自动驾驶大模型展现认知驱动新境界

在2024年北京国际汽车展的舞台上,众多国产车型纷纷亮相,各自展示着独特的魅力。其中,小米SUV7以其精美的外观设计和宽敞的车内空间,吸引了无数目光,成为本届车展上当之无愧的明星。然而,车辆的魅力并不仅限…

数据库系统理论——绪论

文章目录 前言一、数据库四个基本概念1、数据2、数据库3、数据库管理系统(DBMS)4、数据库系统(DBS) 二、数据模型1、概念数据模型2、逻辑数据模型3、物理数据模型 三、三级模式1、图片解析2、二级映像 前言 最近很长时间没更新学…

皮秒激光切割机可以切割材料及主要应用行业

皮秒激光切割机可以切割多种材料,主要应用行业包括但不限于: 1. PCB板行业:主要用于PCB激光分板,如FR4、补强钢片、FPC、软硬结合板、玻纤板等材料的紫外激光切割。 2. 薄膜材料切割:皮秒紫外激光切割机可以直接切割薄…

无法添加以供审核,提交以供审核时遇到意外错误。如果问题仍然存在,请联系我们

遇到问题: 无法添加以供审核 要开始审核流程,必须提供以下项目: 提交以供审核时遇到意外错误。如果问题仍然存在,请联系我们。 解决办法: 修改备案号为小写, 例如:京ICP备2023013223号-2A 改…

选择了软件测试,你后悔吗?

记得在求职的时候,面试官经常问我:“为什么要选择软件测试工作?”而我也会经常说一堆自己有的没的优势去应付。 工作这么久了,也不再浮躁,静下心来回忆当初选择软件测试工作的历程,也是对自己职业生涯的一次回顾。 下…

初始Linux(基础命令)

前言: 我们不能总沉浸在编程语言中,虽然代码能力提升了,但是也只是开胃小菜。我们要朝着更高的方向发展。 最近小编一直在刷力扣,以至于博客更新的比较少。今天就带各位开始学习全新的知识——Linux.至于为啥要学? Lin…

[正则表达式]正则表达式语法与运用(Regular Expression, Regex)

0. 在线工具 RegExr: Learn, Build, & Test RegEx 1. 场景列举 vim Linux命令行 sublime 编辑器 java、python等语言中 ... ... 不同场景、不同版本语法可能不一样 2. 以下示例数据与基本语法 &2024 &As20242024# 2024sA#abdcefgha_bdcefghABASDSADAASDASD…

MySQL之聚合函数与应用

1. 前言 上文我们讲到了单行函数.实际上SQL还有一类叫做聚合函数, 它是对一组数组进行汇总的函数, 输入的是一组数据的集合, 输出的是单个值. 2. 聚合函数 用于处理一组数据, 并对一组数据返回一个值. 有如下几种聚合函数 : AVG(), SUM(), MAX(), MIN(), COUNT(). 3. AVG(…

[蓝桥杯]真题讲解:班级活动(贪心)

[蓝桥杯]真题讲解&#xff1a;班级活动&#xff08;贪心&#xff09; 一、视频讲解二、正解代码1、C2、python33、Java 一、视频讲解 [蓝桥杯]真题讲解&#xff1a;班级活动&#xff08;贪心&#xff09; 二、正解代码 1、C #include<bits/stdc.h> using namespace st…

28.leetcode---前K个高频单词(Java版)

题目链接: https://leetcode.cn/problems/top-k-frequent-words/description/ 题解: 代码: 测试:

Offline:IQL

ICLR 2022 Poster Intro 部分离线强化学习的对价值函数采用的是最小化均方bellman误差。而其中误差源自单步的TD误差。TD误差中对target Q的计算需要选取一个max的动作&#xff0c;这就容易导致采取了OOD的数据。因此&#xff0c;IQL取消max,&#xff0c;通过一个期望回归算子…

QT creator qt6.0 使用msvc2019 64bit编译报错

qt creator qt6.0报错&#xff1a; D:\Qt6\6.3.0\msvc2019_64\include\QtCore\qglobal.h:123: error: C1189: #error: "Qt requires a C17 compiler, and a suitable value for __cplusplus. On MSVC, you must pass the /Zc:__cplusplus option to the compiler."…

PXE批量网络装机和Kickstart无人值守安装

一、PXE定义 PXE&#xff08;preboot execute environment&#xff09;:用于通过网络来引导系统的标准&#xff0c;工作在Client/Server模式&#xff08;也称为CS模式&#xff09;&#xff0c;允许客户机通过网络从远程服务器上下载引导镜像&#xff0c;并加载安装文件或整个操…

劝退计算机?CS再过几年会没落!?

事实上&#xff0c;未来计算机不仅不会没落&#xff0c;国家还会大力发展 只不过大家认为的计算机就是什么Java web&#xff0c;真正的计算机行业是老美那样的&#xff0c;涉及到方方面面&#xff0c;比如&#xff1a; web&#xff0c;图形学&#xff0c;Linux系统开发&#…

酷得智能电子方案 早教学习机

早教学习机是用户友好的&#xff0c;易于操作&#xff0c;同时要确保内容的科学性和适宜性&#xff0c;以促进儿童的健康成长和智力发展。 通常包括以下几个方面&#xff1a; 1.年龄分级内容&#xff1a;软件会根据儿童的不同年龄段提供相应的教育内容&#xff0c;从新生儿到…

renren-fast开源快速开发代码生成器

简介 renrenfast框架介绍 renren-fast是一个轻量级的Spring Boot快速开发平台&#xff0c;能快速开发项目并交付.完善的XSS防范及脚本过滤&#xff0c;彻底杜绝XSS攻击实现前后端分离&#xff0c;通过token进行数据交互 使用流程 项目地址 https://gitee.com/renrenio/ren…

鸿蒙 DevEcoStudio:组件实例(页面及组件生命周期函数)

【使用onPageshow等生命周期函数】 在entry/src/main/ets/pages路径下创建Page1.ets: import router from ohos.router Entry Component struct Page1 {State message: string Hello WorldState show: booleantrueaboutToAppear(){console.log(Page1组件创建实例)}aboutToDisa…

夏天旅行,就认准这五款随身WiFi!准没错!2024随身wifi靠谱品牌推荐,高性价比高口碑随身wifi推荐

过了五一&#xff0c;气温逐渐上升&#xff0c;又到了最适合旅行的季节。这个时候一款趁手的随身WiFi当然是必不可少的&#xff01;不但能解决出行时信号差的烦恼&#xff0c;还可以解决流量不够用的问题。那么&#xff0c;都有哪些随身WiFi在夏季出行时最值得选择呢&#xff1…

docker容器安装sqlserver

docker容器安装sqlserver 搜索SQL Server镜像下载SQL Server镜像创建容器 搜索SQL Server镜像 docker search mssql-server下载SQL Server镜像 docker pull microsoft/mssql-server-linux创建容器 docker run -e ACCEPT_EULAY -e SA_PASSWORD<YourStrong!Passw0rd> -…

庐山西海服务区:从高速服务区到旅游热点的华丽转身

五一假期期间&#xff0c;庐山西海服务区以其独特的魅力吸引了众多游客的目光。曾经只是一个供汽车加油和休息的普通服务区&#xff0c;如今却焕发出了绚丽的光彩&#xff0c;成为了周边地区备受瞩目的旅游热点。庐山西海服务区的转型&#xff0c;不仅为游客带来了丰富多样的娱…