Java设计模式 - 装饰者模式

不断学习才是王道

继续踏上学习之路,学之分享笔记

总有一天我也能像各位大佬一样

原创作品,更多关注我CSDN: 一个有梦有戏的人

准备将博客园、CSDN一起记录分享自己的学习心得!!!

分享学习心得,欢迎指正,大家一起学习成长!

简介

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

装饰者模式实例

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

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

具体的类图如下

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

①、抽象类

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

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设计模式 - 装饰者模式的更多相关文章

  1. JAVA设计模式之【装饰者模式】

    JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...

  2. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  3. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  4. JAVA设计模式初探之装饰者模式

    定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种 ...

  5. java设计模式-观察者模式,装饰者模式

    1.1定义 慨念:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 即:主题和观察者定义了一对多的关系,观察者依赖于主题,只要主题发生变化,观察者就 ...

  6. Java设计模式系列之装饰者模式

    装饰者模式的定义 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案  装饰者模式的UML类图 一般来说装饰者模式有下面几个参与者: Component:装饰者和被装饰者共同 ...

  7. 设计模式学习心得<装饰器模式 Decorator>

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...

  8. 【读书笔记】读《JavaScript设计模式》之装饰者模式

    一.定义 装饰者模式可用来透明地把对象包装在具有同样接口的另一个对象之中.这样一来,你可以给一个方法添加一些行为,然后将方法调用传递给原始对象.相对于创建子类来说,使用装饰者对象是一种更灵活的选择(装 ...

  9. 设计模式のDecoratorPattern(装饰器模式)----结构模式

    一.产生背景 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...

  10. 设计模式C++实现——装饰者模式

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/walkerkalr/article/details/28633123 模式定义:         装 ...

随机推荐

  1. docker compose 部署 minio

    1.docker-compose.yaml 文件如下: version: '3' services: minio: image: minio/minio:latest # 原镜像`minio/mini ...

  2. [ZJCTF 2019]NiZhuanSiWei 1

    考察知识点:反序列化.php伪协议 1.打开之后获得源码信息,如下: <?php $text = $_GET["text"]; $file = $_GET["fil ...

  3. 1_day01_操作系统安装

    操作系统安装 内容介绍 1.制作U盘启动器 2.备份驱动 3.安装操作系统 4.驱动更新 5.依赖库检测 6.系统漏洞修复 7.系统布局优化 一.制作U盘启动器 1.1 下载老毛桃 下载老毛桃pe工具 ...

  4. ETL工具 Flume (一)

    分布式日志采集系统Flume学习 一.Flume架构 1.1 Hadoop业务开发流程 1.2 Flume概述 flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统. 支持在日志系统 ...

  5. 新建 Microsoft Office Word 文档 来源:牛客网

    题目 链接:https://ac.nowcoder.com/acm/contest/28886/1015 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其 ...

  6. redis集群的三种方式

    Redis三种集群方式:主从复制,哨兵模式,Cluster集群. 主从复制 基本原理 当新建立一个从服务器时,从服务器将向主服务器发送SYNC命令,接收到SYNC命令后的主服务器会进行一次BGSAVE ...

  7. mysql 01: source命令

    使用mysql的source命令,执行sql脚本 之所以使用docker同步挂载卷的方法,是因为在docker中运行的mysql未安装vim或gedit等基本编辑器 不方便在mysql容器里直接写sq ...

  8. python:GUI图形化数据库巡检工具

    问题描述:时间过得真快,一眨眼又一个月过去,2022又过去大半,7月的尾巴,终于稍微做出来点 东西,本人也不是开发,也是在不断学习的一枚小白.这次使用tkinter制作了一个mysql的巡检工具,使用 ...

  9. 还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_173 一般情况下,当你想为你的Python开发环境选择一个基础镜像时,大多数人都会选择Alpine,为什么?因为它太小了,仅仅只有 ...

  10. React报错之Objects are not valid as a React child

    正文从这开始~ 总览 当我们尝试在JSX代码中,直接渲染对象或者数组时,会产生"Objects are not valid as a React child"错误.为了解决该错误, ...