设计模式 - 结构型模式考点篇:装饰者模式(概念 | 案例实现 | 优缺点 | 使用场景)

news2024/11/19 0:26:18

目录

一、结构型模式

1.1、装饰者模式

1.1.1、概念

1.1.2、案例实现

1.1.3、优缺点

1.1.4、使用场景


一、结构型模式


1.1、装饰者模式

1.1.1、概念

装饰者模式就是指在不改变现有对象结构的情况下,动态的给该对象增加一些职责(增加额外功能)的模式.

例如,现在要开发一个点餐系统,有一个抽象类快餐类,快餐店里有炒面、炒饭,分别去继承实现.  如果现在需要添加额外的配料(比如 鸡蛋),那么计算额外加钱就会不叫麻烦,就需要分别给 炒面类 和 炒饭类 定义一个子类(鸡蛋炒面类、鸡蛋炒饭类).  再者,如果要新增一个快餐类(比如 凉皮),就需要定义更多的子类.  通过装饰者模式就可以在不需要添加子类的情况下,动态的添加配料.

装饰者模式中的角色如下:

  • 抽象构件角色:定义一个抽象接口用来规范附加的对象(比如上述的 快餐类).
  • 具体构件角色:实现抽象构件,将来会被添加一些职责(比如上述的 炒面类 和 炒饭类).
  • 抽象装饰角色:继承抽象构件 和 持有抽象构件的引用,可以通过 子类 扩展具体的构件.
  • 具体装饰角色:继承抽象装饰,重写相关方法,给具体的构件对象添加附加责任.

1.1.2、案例实现

实现上述案例.

/**
 * 抽象构建角色: 快餐
 */
public abstract class FastFood {

    private float price; //价格
    private String desc; //描述
    public abstract float cost(); //获取最终价格

    public FastFood() {
    }

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

    public float getPrice() {
        return price;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
    
}
/**
 * 具体构建角色: 炒饭类
 */
public class Rice extends FastFood{

    public Rice() {
        super(10, "炒饭");
    }

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

}
/**
 * 具体构建角色: 面条类
 */
public class Noodles extends FastFood {

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

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

}
/**
 * 抽象装饰角色: 配料类
 */
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;
    }

}
/**
 * 抽象装饰角色: 配料类
 */
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;
    }

}
/**
 * 具体装饰角色: 鸡蛋配料
 */
public class Egg extends Garnish{

    public Egg(FastFood fastFood) {
        super(fastFood, 1, "鸡蛋");
    }

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

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }

}
/**
 * 具体装饰角色: 培根配料
 */
public class Bacon extends Garnish{

    public Bacon(FastFood fastFood) {
        super(fastFood, 2, "培根");
    }

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

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }

}
public class Client {

    public static void main(String[] args) {
        //1.带你一份炒饭
        FastFood food = new Rice();
        System.out.println(food.getDesc() + "  " + food.cost() + "元");
        System.out.println("================");
        //2.加一份鸡蛋
        food = new Egg(food);
        System.out.println(food.getDesc() + "  " + food.cost() + "元");
        System.out.println("================");
        //3.加一份鸡蛋
        food = new Egg(food);
        System.out.println(food.getDesc() + "  " + food.cost() + "元");
        System.out.println("================");
        //4.加一个培根
        food = new Bacon(food);
        System.out.println(food.getDesc() + "  " + food.cost() + "元");
    }

}

执行结果如下:

1.1.3、优缺点

优点:

动态扩展:比继承具有更好的扩展性(继承时静态附加责任,装饰者时动态添加责任),可以在不修改原类的情况下,给对象添加责任.

缺点:

增加系统复杂度:装饰者比继承使用的类可能会少,但比继承使用的对象可能更多,更多的对象在程序排查错误的时候可能更复杂.

1.1.4、使用场景

1. 当不能采用继承的方式对程序进行扩展,比如存在大量的独立扩展,为了支持每一种组合产生大量子类(例如上述栗子中的给 炒饭加鸡蛋,导致出现 鸡蛋炒饭类),导致子类数目爆炸增长、或者是 类定位为 final 类型(不能继承).

2. 在不影响其他类的情况下,以动态的方式添加责任.

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

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

相关文章

IsaacGym四足机器人sim to real全过程详细解析(walk these ways方法)

四足机器人强化学习控制第三篇 第一篇 Isaac Gym环境安装和四足机器人模型的训练 第二篇 docker中安装ROS 在宇树四足机器人运行 强化学习GenLoco算法 目录 四足机器人强化学习控制第三篇前言一、安装和配置二、训练1.训练2.恢复训练3.训练结果 三、sim to real1.部署模型注意…

重生奇迹MU天空之城玩转攻略

现在依然有众多玩家喜欢重生奇迹MU 游戏,游戏设计非常完善,后续推出了重生奇迹MU 版本,在设计方面更加炫酷,各种游戏玩法以及模式,让众多玩家感受到不错的游戏体验。 游戏由很多的地图组成,重生奇迹MU 大陆…

【Redis】List列表相关的命令

目录 命令LPUSHLPUSHXLRANGERPUSHRPUSHXLPOPRPOPLINDEXLINSERTLLENblpop和brpop 命令 LPUSH 将⼀个或者多个元素从左侧放⼊(头插)到list中。 LPUSH key element [element ...]LPUSHX 在key存在时,将⼀个或者多个元素从左侧放⼊&#xff08…

【好文推荐】openGauss索引推荐功能测试

一、单索引推荐 单索引推荐功能,目前支持select查询,看官方介绍类似oracle中的sql_tunning_adviser,不过只是推荐创建索引。根据sql优化原理,猜测应该时根据选择来推荐索引。 1、查看sqlPanWeiDB# create table t2 as select * from pg_tab…

家政预约服务APP小程序搭建,功能支持定制

家政预约服务APP小程序搭建,功能支持定制,后期升级无忧.团队自主研发家政APP系统,正版源码,售后技术保障! 家政系统客户端 搭建专属私城流量平台,让您插上互联网的翅膀。找月嫂,育婴…

Docker镜像容器简单案例

我们安装完Docker之后就可以练习了. 镜像 案例1-拉取、查看镜像 1)首先去镜像仓库搜索nginx镜像,比如 : Docker Hub Container Image Library | App Containerization 搜索我们想要拉取的镜像 , 例如: nginx 复制命令: docker pull nginx …

性能测试之稳定性测试和并发压力测试的TPS计算

1、稳定性测试TPS计算 ①普通计算公式:TPS总请求数 / 总时间按照需求得到基础数据,在去年第20周,某平台有5万的浏览量那么总请求数我们可以估算为5万(1次浏览都至少对应1个请求)总请求数 50000请求数总时间&#xff1…

Spring Task简单说明

1.导入坐标 说明&#xff1a;自带有spring-context。 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>${aliyun.sdk.oss}</version> </dependency> 2. 启动类添加注解 pac…

ubuntu下查看realsense摄像头查看支持的分辨率和频率

引言&#xff1a; 在实际应用中&#xff0c;摄像头的频率如果过高&#xff0c;可能会造成系统图像处理的压力过大&#xff0c;因此需要选择合适的参数才能达到预期的效果。本文主要探讨设置realsense相关参数 1、打开终端&#xff0c;输入rs-enumerate-devices rs-enumerate-…

超市微信小程序是怎么做的

市微信小程序是利用微信小程序平台为超市或零售商提供线上销售服务的一种应用。通过小程序&#xff0c;超市可以向消费者提供更加便捷、快速、个性化的购物体验&#xff0c;从而提升销售业绩、增加客户满意度。以下是超市微信小程序可以实现的一些主要功能。 一、商品展示与搜索…

现货黄金指标之王是什么

很多现货黄金投资在日常看盘的交易的时候&#xff0c;都会借助各种各样的技术指标来辅助自己的分析&#xff0c;但其实好用的技术指标两三个就足够了。如果有那么一个指标&#xff0c;可以帮助投资者辨清趋势&#xff0c;把握行情走势的大局&#xff0c;一定会是大受市场欢迎。…

spring 事务源码阅读之实现原理

开启事务 使用EnableTransactionManagement注解开启事务 该注解会引入TransactionManagementConfigurationSelector类&#xff0c;然后该类导入两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration。 1、添加bean后置处理器 AutoProxyRegistrar类的作用是注…

数字IC前端学习笔记:数字乘法器的优化设计(基2布斯乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 ​​​​​​​在之前的文章中&#xff0c;进位保留乘法器、华莱士树乘法器、dadda树乘法器等方法都是优化了部分积累加这个过程。还有一些​​​​​​​方法能对…

再获深交所认可,Smartbi实力领跑金融BI赛道

“十四五”规划中提到&#xff0c;健全具有高度适应性、竞争力、普惠性的现代金融体系&#xff0c;构建有效支撑实体经济的体制机制。《证券期货业科技发展“十四五”规划》作为指导证券期货业科技发展的纲领性文件&#xff0c; 秉承国家“十四五”规划的数字化发展理念&#x…

在PCB走线中线不直,有小疙瘩,让走线变直的方法

在PCB走线中线不直,导线上有小疙瘩,那么如何去除呢? 在PCB走线的过程中,鼠标右击,点击Enhanced Pad Entry(增强焊盘入口)选项去勾。 Enhanced Pad Entry去勾后,然后再走线,走线就很直了。 如下图所示。 博主专注职场硬件设计,如果文章对你有帮助,请关注,点赞,收藏…

clickhouse之readonly解决方法

1&#xff0c;问题描述 日志报错写入ck报错&#xff1a;ru.yandex.clickhouse.except.ClickHouseUnknownException: ClickHouse exception, code: 1002, host: 192.16.1.19, port: 8123; Code: 242. DB::Exception: Table is in readonly mode: replica_path/clickhouse/tables…

8+肿瘤+多组机器学习+分型。

今天给同学们分享一篇肿瘤多组机器学习分型的生信文章“Integrated multiomics analysis and machine learning refine molecular subtypes and prognosis for muscle-invasive urothelial cancer”&#xff0c;这篇文章于2023年6月5日发表在Mol Ther Nucleic Acids期刊上&…

全志R128芯片应用开发案例——按键输入

按键输入 本文案例代码下载地址按键输入案例代码https://www.aw-ol.com/downloads?cat24 首先我们搭建电路&#xff0c;如下&#xff1a; 引脚按键PA25按键1脚GND按键3脚 载入方案 我们使用的开发板是 R128-Devkit&#xff0c;需要开发 C906 核心的应用程序&#xff0c;所…

金融行业蓄电池监控,究竟有多厉害!

金融行业是现代社会的重要组成部分&#xff0c;金融机构依赖于高度可靠的电力系统来支持其日常运营。随着金融交易日益数字化和自动化&#xff0c;电力中断或失效可能导致严重的财务损失和风险。 因此&#xff0c;金融行业对电力供应的可靠性要求极高&#xff0c;而蓄电池监控正…

Vue3+vite 添加router后的2个坑

废话不多说&#xff0c;发现问题并解决问题 第 1 个坑&#xff1a;关于 …/ router 报红 正常引入页面路由&#xff0c;页面也显示出来了&#xff0c;路径也是正确的&#xff0c;但是却报红了。 原因是&#xff1a;当前路径正则有问题 解决方案&#xff1a; 在 src 文件下 v…