【设计模式】Java设计模式-装饰者模式

Java设计模式 – 装饰者模式

😄 不断学习才是王道
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆原创作品,更多关注我CSDN: 一个有梦有戏的人
👊准备将博客园、CSDN一起记录分享自己的学习心得!!!
🌝分享学习心得,欢迎指正,大家一起学习成长!

【设计模式】Java设计模式-装饰者模式

简介

装饰者模式是一种结构型模型,是动态的给对象增加职责,对于新增功能来说要比通过子类方式更加的灵活。他允许对一个对象进行添加新的功能,但不能改变结构。

装饰者模式实例

德德奶茶店里有许多种奶茶,奶茶还能根据自己的喜欢添加额外的料。加入奶茶有很多种,料也有很多,要求既能够在扩展奶茶种类的时候,改动方便,不能改变结构。使用面向对象的方式计算不同种类奶茶的费用。用户可以只买不加料,也可以买奶茶再根据自己的喜好加料。

既想实现需求,又不能让类太繁重,又要做到高扩展,改动方便。于是就使用了装饰者模式,简单说一下如何使用装饰者首先需要一个抽象类,里面除了价格等属性,还需要有个能够让子类实现的抽象方法来计算费用。具体的奶茶再来继承这个抽象类,实现其方法并设置初始值。还需要定义总体装饰者,他是继承了抽象类,采用组合的方式,计算总价格,其他真正地装饰者也就是调料,他们再去继承这个总体装饰者。使用的使用只要实例化父类,对象为具体的奶茶类型,在加料的时候,只需要把这杯奶茶送到装饰者上,去让装饰者装饰,最后返回还是这个父类。
具体的类图如下

【设计模式】Java设计模式-装饰者模式

接下来一步一步编写代码来实现买一杯 红豆奶茶 + 牛奶 + 布丁

①、抽象类

定义饮料-抽象类,包含描述和费用两个属性,还有个抽象方法-计算价格,提供给子类去实现。

package com.lyd.demo.drink;
/**
 * @Author: lyd
 * @Description: 饮料-抽象类
 * @Date: 2022-08-29
 */
public abstract class Drink {
    private String describe; // 描述
    private float price = 0.0f;
    public String getDescribe() {
        return describe;
    }
    public void setDescribe(String describe) {
        this.describe = describe;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    // 计算费用 - 抽象 - 子类实现
    public abstract float cost();
}

②、定义单体类

定义奶茶类,只需要继承饮料类,并且获取父类的价格。

package com.lyd.demo.drink;
/**
 * @Author: lyd
 * @Description: 奶茶类
 * @Date: 2022-08-29
 */
public class MilkTea extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}

③、定义具体奶茶

红豆奶茶和珍珠奶茶的代码相似,这里只粘贴红豆奶代码。具体奶茶,要设置描述和单价。

package com.lyd.demo.drink;
/**
 * @Author: lyd
 * @Description: 红豆奶茶
 * @Date: 2022-08-29
 */
public class RedBeanMilkTea extends MilkTea {
    public RedBeanMilkTea() {
        setDescribe(" 红豆奶茶 ");
        setPrice(7.0f);
    }
}

④、定义装饰类

总体装饰者,继承饮料类

package com.lyd.demo.decorator;
import com.lyd.demo.drink.Drink;
/**
 * @Author: lyd
 * @Description: 装饰者
 * @Date: 2022-08-29
 */
public class Decorator extends Drink {
    Drink drink;
    public Decorator(Drink drink) { // 组合
        this.drink = drink;
    }
    @Override
    public float cost() {
        // 计算价格综合
        return super.getPrice() + drink.cost();
    }
    @Override
    public String getDescribe() {
        return drink.getDescribe() + " + " + super.getDescribe() + " " + super.getPrice();
    }
}

⑤、定义具体装饰者

具体装饰者就是要添加的料,这里只粘贴单个代码示例,其他相似。

package com.lyd.demo.decorator;
import com.lyd.demo.drink.Drink;
/**
 * @Author: lyd
 * @Description: 装饰器 - 牛奶
 * @Date: 2022-08-29
 */
public class Milk extends Decorator {
    public Milk(Drink drink) {
        super(drink);
        setDescribe(" 牛奶 ");
        setPrice(3.0f);
    }
}

⑥、测试实例

买一杯 红豆奶茶 + 牛奶 + 布丁。
通过父类实例化具体的奶茶子类,调用其计算总价方法;要是需要加料,只要把奶茶实例放到new调料实例中,让装饰者去装饰这个类,最后返回也是饮料类。通过层层套入装饰的方式就实现了装饰者模式。在此,如果是买第二杯奶茶,只需要在new一个对应奶茶的实例。如果还有额外的品种奶茶需要添加,只要继续添加xx奶茶类,不会改变结构,或者是需要添加调料,也是如此操作,让其多个具体的装饰者。

package com.lyd.demo.test;
import com.lyd.demo.decorator.Milk;
import com.lyd.demo.decorator.Pudding;
import com.lyd.demo.drink.Drink;
import com.lyd.demo.drink.PearlMilkTea;
/**
 * @Author: lyd
 * @Description: 测试类
 * @Date: 2022-08-29
 */
public class DecorateTest {
    public static void main(String[] args) {
        // 买一杯 红豆奶茶 + 牛奶 + 布丁
        // 实例化为父类对象,红豆奶茶
        Drink pearlMilkTea = new PearlMilkTea();
        // 先观察红豆奶茶的输出
        System.out.println("您购买了: " + pearlMilkTea.getDescribe());
        System.out.println("您购买的费用: " + pearlMilkTea.cost());
        // 添加牛奶之后
        System.out.println("添加牛奶之后");
        pearlMilkTea = new Milk(pearlMilkTea);
        System.out.println("您购买了: " + pearlMilkTea.getDescribe());
        System.out.println("您购买的费用: " + pearlMilkTea.cost());
        // 再添加布丁之后
        System.out.println("再添加布丁之后");
        pearlMilkTea = new Pudding(pearlMilkTea);
        System.out.println("您购买了: " + pearlMilkTea.getDescribe());
        System.out.println("您购买的费用: " + pearlMilkTea.cost());
    }
}

运行结果:

【设计模式】Java设计模式-装饰者模式

好文推荐

👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得一键三连哦!👍

看过百遍,还不如动手一遍,动手敲敲代码有助于理解,设计模式不是很容易就理解,需要动手尝试,这样不仅能够学会设计模式,更能够更好的理解java面向对象。

Original: https://www.cnblogs.com/lyd-code/p/16684312.html
Author: 怒放吧德德
Title: 【设计模式】Java设计模式-装饰者模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574130/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • CKS考试心得分享

    CKS证书 考试相关 考试报名准备 CKS考试和CKA考试一样,已经开放中国大陆的考试。但区别是CKS目前没有中文题目,考试都是英文题目,唯一区别是CKS中文考试是中文老师监考,仅…

    Linux 2023年6月13日
    0107
  • Redis安装及HA(High Availability)配置

    Redis是一种内存数据库,以KEY-VALUE(即键值对)的形式存储数据。这篇文章主要介绍的是Redis安装及配置,所以不对Redis本身作详细介绍了。 下 载: 解 压: 以r…

    Linux 2023年5月28日
    080
  • 二进制插入

    二进制插入__牛客网 (nowcoder.com) 题意为 让m插入到n的第j位到第i位 方法1: class BinInsert { public: int binInsert(…

    Linux 2023年6月13日
    0102
  • 站长工具

    背景 日常测试全国各种某网站的响应情况使用 站长工具 站长工具 http://tools.wujingquan.com/ 站长工具 ping检测 ping检测 https://pi…

    Linux 2023年6月6日
    0113
  • GitHub中Fork来的仓库如何进行双向更新

    [TOC](文章目录) 一、做点贡献 想对别人的某个仓库”做点贡献”怎么办? 1. Fork该仓库 首先Fork该仓库,本文以git-learn这个仓库为例…

    Linux 2023年6月7日
    0117
  • cron 表达式

    cron 表达式 1.简介:一个cron表达式最少有5个空格来分割时间元素,总共有7个元素,分别如下: ① 秒(0-59) ② 分钟(0-59) ③ 小时(0-23) ④ 天(月的…

    Linux 2023年6月7日
    070
  • archLinux 配置用户

    archlinux 启动之后只有默认的root用户,首先介绍下系统启动到登录需要的步骤 1.系统通过systemd 以pid为1初始化系统,启动系统用户和系统必要的服务,(这一步目…

    Linux 2023年6月13日
    080
  • 玩转SpringBoot之捣鼓 Redis

    我们都知道,把首页数据放到Redis里,能够加快首页数据的访问速度。但是我们要如何准确又快速的将 Redis 整合到自己的 SpringBoot2.x 项目中呢?今天阿淼就带大家爬…

    Linux 2023年5月28日
    0120
  • 保姆教程系列一、Linux搭建Nacos

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 简介: Nacos是阿里巴巴开源的一款支持服务注册与发现,配置管理以及微服务管理的组件。用来取代以前常用的注册中心…

    Linux 2023年6月14日
    092
  • 本篇还玩“障眼法”,一文解读HTML内联框架Iframes。

    写在开篇 假设有一个需求,想要在网页内显示其它网页,怎么搞?很简单,可以用iframe来解决,那啥是iframe?本篇的主题就是它,接下来我们一一解剖它的用法。 嵌入第三方url页…

    Linux 2023年6月7日
    0126
  • vue+vant音乐播放器(andriod)项目

    新建项目 在适合的目录下打开终端输入vue create music_player,回车 选择Default([Vue 2] babel,eslint) 等待项目构建完成 项目构建…

    Linux 2023年6月13日
    090
  • Kubernetes中的网络

    一、引子 既然Kubernetes中将容器的联网通过插件的方式来实现,那么该如何解决这个的联网问题呢? 如果你在本地单台机器上运行docker容器的话注意到所有容器都会处在 doc…

    Linux 2023年6月14日
    096
  • Ubuntu 进程 线程 查看 设置(top taskset)

    top 的基本使用 taskset 的基本使用 top top 详解 及 使用 top 常用的命令 taskset taskset 的基本使用 1. 显示某个进程(线程)运行所在的…

    Linux 2023年6月6日
    0118
  • 汉诺塔

    设计并实现一个游戏:汉诺塔。完成这个实验,涉及C++面向对象编程以及基本的数据结构知识(如栈和队列)但具此次实现并没有使用STL库。 1. 汉诺塔问题 汉诺塔是一个著名的数学问题。…

    Linux 2023年6月13日
    095
  • Swagger2 Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is java.lang.NullPointerException报错

    报错信息: Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is java.la…

    Linux 2023年6月14日
    078
  • bash 中 echo & printf

    首先列一下今天收获的消息 sh是: Bourne Shell(/usr/bin/sh或/bin/sh) bash是: Bourne Again Shell(/bin/bash) p…

    Linux 2023年6月6日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球