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

目录

一、结构型模式

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, "炒饭");}@Overridepublic float cost() {return getPrice();}}
/*** 具体构建角色: 面条类*/
public class Noodles extends FastFood {public Noodles() {super(12, "炒面");}@Overridepublic 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, "鸡蛋");}@Overridepublic float cost() {return getPrice() + getFastFood().cost();}@Overridepublic String getDesc() {return super.getDesc() + getFastFood().getDesc();}}
/*** 具体装饰角色: 培根配料*/
public class Bacon extends Garnish{public Bacon(FastFood fastFood) {super(fastFood, 2, "培根");}@Overridepublic float cost() {return getPrice() + getFastFood().cost();}@Overridepublic 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.hqwc.cn/news/131665.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++设计模式之责任链模式:行为型】分析及示例

简介 责任链模式是一种行为型设计模式,它允许将请求沿着处理链传递,直到有一个处理器能够处理该请求。这种模式将请求的发送者和接收者解耦,同时提供了更高的灵活性和可扩展性。 描述 责任链模式由多个处理器组成一个处理链,每…

PCL源码分析:直通滤波

文章目录 一、简介二、源码分析三、小结参考资料一、简介 让我们从一个最简单的功能开始慢慢重新认识PCL~~,虽然这个功能很简单,但是已可以从中管中窥豹来更加深入了解PCL的内部结构。 二、源码分析 在真正看PCL的源代码之前,我们先简单的看一下直通滤波这个类的类关系: 这…

如何在edge浏览器中给PDF添加文字批注

我用的edge浏览器是目前最新版的(一般自动更新到最新版) 最近,我喜欢用edge浏览器查看PDF,节省电脑资源,快捷且方便。 但edge对PDF的标注种类较少,主要是划线和涂色,文字批注功能尚未出现在工具…

【算法-贪心】无重叠区间-力扣 435 题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

OpenGL LUT滤镜算法解析

1. 简介 滤镜:一些图像处理软件针对性地提供了一些对传统滤镜效果的模拟功能,使图像达到一种特殊效果。滤镜通常需要同通道、图层、色阶等联合使用,才能使图像取得最佳艺术效果。在软件界面中也直接以“滤镜”(Filter&#xff09…

探索 Redis 与 MySQL 的双写问题

在日常的应用开发中,我们经常会遇到需要使用多种不同类型的数据库管理系统来满足各种业务需求。其中最典型的就是Redis和MySQL的组合使用。 这两者拥有各自的优点,例如Redis为高性能的内存数据库提供了极快的读写速度,而MySQL则是非常强大的…

Linux查看本机IP地址

Linux查看本机IP地址 命令 ipconfig可能会遇到的问题 Command ‘ifconfig’ not found, but can be installed with: Command ifconfig not found, but can be installed with:sudo apt install net-tools解决办法 安装net-tools再执行ipconfig 安装网络工具 sudo apt i…

【虚拟机】桥接模式下访问外网

目录 一、桥接模式的作用原理 二、配置桥接模式实现外网访问 1、设置 VMnet0 要桥接的网卡 2、虚拟机选择 VMnet0 网卡 3、手动配置虚拟机IP 一、桥接模式的作用原理 桥接模式相当于在当前局域网里创立了一个单独的主机,该主机桥接到宿主主机的网卡&#xff0…

AI如何帮助Salesforce从业者找工作?

在当今竞争激烈的就业市场中,找到满意的工作是一项艰巨的任务。成千上万的候选人竞争一个岗位,你需要利用一切优势从求职大军中脱颖而出。 这就是AI的用武之地,特别是像ChatGPT这样的人工智能工具,可以成为你的秘密武器。本篇文章…

【python】time

文章目录 【calendar】是否闰年星期英文缩写今天星期几打印日历 【datetime】今天星期几 【time】当前时间 【pandas】当前时间文件修改的时间 【日历】 【calendar】 是否闰年 import calendar print(calendar.isleap(2000))out True星期英文缩写 print(calendar.weekhead…

Python爬虫(二十二)_selenium案例:模拟登陆豆瓣

本篇博客主要用于介绍如何使用seleniumphantomJS模拟登陆豆瓣,没有考虑验证码的问题,更多内容,请参考:Python学习指南 #-*- coding:utf-8 -*-from selenium import webdriver from selenium.webdriver.common.keys import Keysimp…

金融信创黄金三年:小程序生态+跨端技术框架构建

小程序应用场景生态的发展,受益于开源技术的发展,以及响应快速开发的实际业务需求,一些跨端框架如:Electron、wxPython、FinClip、Tauri、Flutter等发展也非常迅速,小程序生态跨端技术框架,不仅能满足自有超…