java设计模式之装饰者模式

news2024/11/16 3:49:13

一:装饰者模式

1.什么是装饰者模式?
装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
装饰者模式的基本介绍
1.装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
2.这里提到的动态的将新功能附加到对象和ocp原则,在后面的应用实例上会以代码的形式体现,请同学们注意体会。

2.装饰者模式适合应用场景
1.如果你希望在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为, 可以使用装饰模式。
2.如果用继承来扩展对象行为的方案难以实现或者根本不可行, 你可以使用该模式

3.装饰者模式优缺点
优点:
1.你无需创建新子类即可扩展对象的行为。
2.你可以在运行时添加或删除对象的功能。
3.你可以用多个装饰封装对象来组合几种行为。
4.单一职责原则。 你可以将实现了许多不同行为的一个大类拆分为多个较小的类。
5.开闭原则。 你可以在不对服务或客户端做出修改的情况下创建新代理。
缺点:
1.在封装器栈中删除特定封装器比较困难。
2.实现行为不受装饰栈顺序影响的装饰比较困难。
3.各层的初始化配置代码看上去可能会很糟糕。

4.装饰者模式角色:
抽象构件(Component)角色 :定义一个抽象接口以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色 :实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰(Decorator)角色 : 继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰(ConcreteDecorator)角色 :实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

二:装饰者模式代码实现

案例:
快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额外加钱,
每个配菜的价钱通常不太一样,那么计算总价就会显得比较麻烦。
在这里插入图片描述
抽象构件

/**
 * @Author cgz
 * @Date 2022/11/17 14:52
 */
//快餐接口(抽象构件)
public abstract class FastFood {

    private float price;
    private String desc;

    public FastFood() {
    }

    public FastFood(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public float getPrice() {
        return price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    //这个接口是这个产品都有的特点,比如每个快餐我们都需要知道他的价格
    public abstract float cost(); //获取价格

}

具体构件


/**
 * @Author cgz
 * @Date 2022/11/17 14:53
 */
//炒面(具体构件)
public class FriedNoodles extends FastFood{

    public FriedNoodles() {
        super(12, "炒面");
    }

    @Override
    public float cost() {
        return getPrice();
    }
}


/**
 * @Author cgz
 * @Date 2022/11/17 14:53
 */
//炒饭(具体构件)
public class FriedRice extends FastFood{
    public FriedRice() {
        super(10, "炒饭");
    }
    public float cost() {
        return getPrice();
    }

}

抽象装饰

/**
 * @Author cgz
 * @Date 2022/11/17 14:54
 */
//抽象装饰(继承父类并且扩展,比如在炒饭或者炒面的基础上再加一些产品进来:鸡蛋、培根)
public abstract class Garnish extends FastFood {
    private FastFood fastFood;

    public FastFood getFastFood() {
        return fastFood;
    }

    public void setFastFood(FastFood fastFood) {
        this.fastFood = fastFood;
    }

    public Garnish(FastFood fastFood, float price, String desc) {
        super(price, desc);
        this.fastFood = fastFood;
    }
}

具体装饰

/**
 * @Author cgz
 * @Date 2022/11/17 14:56
 */
//具体装饰(扩展的)
public class Bacon extends Garnish{
    public Bacon(FastFood fastFood) {
        super(fastFood,2,"培根");
    }
    @Override
    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }
    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }

}

/**
 * @Author cgz
 * @Date 2022/11/17 14:55
 */
//鸡蛋配料(具体装饰)(扩展的)
public class Egg extends Garnish{
    public Egg(FastFood fastFood) {
        super(fastFood,1,"鸡蛋");
    }
    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }
    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}


测试类

 public static void main(String[] args) {
        //点一份炒饭
        FastFood food = new FriedRice();
        //花费的价格
        System.out.println(food.getDesc() + " " + food.cost() + "元");
        System.out.println("========");
        //点一份加鸡蛋的炒饭
        FastFood food1 = new FriedRice();
        food1 = new Egg(food1);
        //花费的价格
        System.out.println(food1.getDesc() + " " + food1.cost() + "元");
        System.out.println("========");
        //点一份加培根的炒面
        FastFood food2 = new FriedNoodles();
        food2 = new Bacon(food2);
        //花费的价格
        System.out.println(food2.getDesc() + " " + food2.cost() + "元");
    }

在这里插入图片描述

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

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

相关文章

Jasper 中如何将数据拆成多行并跨行累计

【问题】 I have a query that returns some summary records. For instance, loan amount, loan term, interest rate. Then I want to have a second row that builds out the detailed payment schedule. so the report would look like this: Loan Amt Term …

SpringBoot2

文章目录1.简介1.1 SpringBoot优缺点1.2 官方文档结构2. SpringBoot入门2.1 HelloWord2.2 依赖管理2.3 自动配置2.4 容器功能组件添加原生配置文件引入2.5 配置绑定ConfigurationPropertiesEnableConfigurationProperties2.6 自动配置原理底层总结最佳实践2.7 开发小技巧Lombok…

UML类图简单认识

类 类图包括类、接口和关系。类中包含三元素,第一行是类名,如果是虚类则为斜体。第二行包括属性,如果是public则为,如果是private则为-,如果是protected则为#。第三行包括方法,方法前面的符号表示与属性的…

QSS的应用

盒子模型: margin 边距border 边框padding 内边距content 内容常用的一些属性: background背景background-color背景颜色background-image背景图片background-position对齐方式border-(top、left、bottom、right)边界border-…

单调栈问题---(每日温度,下一个更大元素Ⅰ)

代码随想录day 58 单调栈问题— 每日温度,下一个更大元素Ⅰ 文章目录1.leetcode 739. 每日温度1.1 详细思路及解题步骤1.2Java版代码示例2.leetcode 496. 下一个更大元素 I2.1 详细思路及解题步骤2.2Java版代码示例1.leetcode 739. 每日温度 1.1 详细思路及解题步骤 这题会用到…

Spark RDD编程模型及算子介绍(一)

文章目录RDD编程模型介绍RDD的两种算子及延迟计算常见的Transformation算子RDD编程模型介绍 RDD是Spark 对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体。每一个RDD都代表着一种分布式数据形态。在RDD的编程模型中,一共有两种算…

Linux-服务管理

服务介绍 服务本质就是进程,但是是运行在后台的,通常都会监听某个端口,等待其他程序的ing求,比如mysqld,sshd,防火墙灯,因为又称为守护进程 如何管理服务 CentOS7.0前使用service命令 servi…

SpringBoot-配置

目录 起步依赖原理分析 配置文件分类 YAML YAML:基本语法 YAML:数据格式 YAML:参数引用 读取配置内容 profile Profile-小结 内部配置加载顺序 外部配置加载顺序 起步依赖原理分析 在spring-boot-starter-parent中定义了各种技术的…

[附源码]Python计算机毕业设计GuiTar网站设计

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

【学习笔记】《模式识别》4:贝叶斯判别准则

贝叶斯判别准则 文章目录贝叶斯判别准则一、研究对象及相关概率1. 两类研究对象2.概率3. 条件概率4. 模式识别中的三个概率5. 两对条件概率的区别二、贝叶斯决策1.最小错误率贝叶斯决策2. 最小风险贝叶斯决策3. (0-1)损失最小风险贝叶斯决策4.正态分布模式的贝叶斯决策三、贝叶…

RFID在钢筋仓库管理中的应用

RFID在钢筋仓库管理中的应用 应用背景 随着经济的迅速发展,带动了钢材业的迅速发展,钢筋的使用量也在改革开放后有了近370多倍的增长,如此大量的钢筋在库存管理,盘点,防盗,各种型号发货、防窜货上等等一系…

图片链接或pdf链接通过浏览器打开时,有时可以直接预览,有时却是下载,为什么?

在前端开发中,有时候需要对一些文件链接进行特殊处理,比如对于一些图片链接或者PDF链接,有时我们需要通过浏览器打开进行预览,有时又不希望通过浏览器进行打开,而是希望能够直接下载到本地。但现实效果却往往跟我们相反…

硅麦驱动开发及调试(pdm>>I2S>>pcm)

pdm 协议 PDM接口只有两根信号线: PDM_CLK 时钟信号。 PDM_DATA 数据信号。 I2S协议 数据发送规格 I2S在BCLK的下降沿发送数据(发送),在上升沿进行数据采样(接收)。每次是先发送最高位,最后…

Hadoop概述

Hadoop概述 Hadoop介绍 狭义上Hadoop值的是Apache的一款开源软件。 用java语言实现开源软件框架 允许使用简单的编程模型跨计算机集群对大型数据集进行分布式处理 Hadoop核心组件 Hadoop HDFS(分布式文件存储管理系统):解决海量数据存储 Hadoop YARN(集群资源管理…

3-2、python内置数据类型(列表和元组)

文章目录序列列表列表的创建列表的基本特性连接操作符和重复操作符成员操作符(in和not in)索引切片for循环列表的常用方法增加修改(通过索引和切片重新赋值)查看删除其他操作元组(和列表相比,不能增删改元素…

30分钟带你精通Git使用

一、 版本控制工具 1.1. 什么是版本控制系统? 版本控制系统(Version Control System):是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制系统不仅可以应用于软件源代码的文本文件,而且…

[附源码]SSM计算机毕业设计班级风采网站JAVA

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

TIA博途中累计流量的两种计算方法示例

TIA博途中累计流量的两种计算方法示例 如下图所示,首先,我们要了解累计流量的含义: 即t1至t2时刻,对瞬时流量求定积分,由上图可知,t1至t2的定积分,即蓝色部分的面积,那么直接求这个面积是有难度的,我们只能用近似的方法来求取, 如下图所示,把该部分面积分割成一个个…

最简单的git图解(git stash)

大家平时开发过程中肯定遇到过这样的情况:代码写了一半,但是需要紧急修改一个bug,还是在当前项目中修改,这时怎么办呢?把写了一半的代码进行提交?可能编译还通不过,或是启动不了,要是…

Java项目:SSH学生学籍管理系统及教务管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本系统包含管理员、教师、学生三种角色; 管理员角色包含以下功能: 管理员登录,学科管理,班级管理,教师管理,学籍信息管理,课表管理…