技术标签: Decorator 装饰者模式 设计模式 23种设计模式
背景
有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。
装饰者模式的定义
装饰者(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
装饰者模式属于对象结构型模式,也体现了开闭原则(ocp)。
装饰者模式的优缺点
优点:
缺点:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
装饰者模式的结构
装饰器模式主要包含以下角色。
装饰者模式的结构图
实现星巴克咖啡+调味品的下单,并计算费用
定义抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
public abstract class Drink {
public String dsc; //描述
private float price = 0.0f; //价格
public String getDsc() {
return dsc;
}
public void setDsc(String dsc) {
this.dsc = dsc;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的抽象方法,由子类实现
public abstract float cost();
}
定义具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
具体构件(ConcreteComponent)角色1:Espresso 意大利咖啡
public class Espresso extends Coffee{
public Espresso(){
setDsc("意大利咖啡");
setPrice(10.0f);
}
}
具体构件(ConcreteComponent)角色2:LongBlack 美式咖啡1
public class LongBlack extends Coffee{
public LongBlack(){
setDsc("美式咖啡1");
setPrice(9.0f);
}
}
具体构件(ConcreteComponent)角色3:LongBlack 美式咖啡2
public class ShortBlack extends Coffee{
public ShortBlack(){
setDsc("美式咖啡2");
setPrice(8.0f);
}
}
定义抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
public class Decorator extends Drink{
//装饰者组合了抽象构件(被装饰者)
private Drink obj;
public Decorator(Drink obj){
this.obj = obj;
}
@Override
public float cost() {
//计算费用:父类的费用 + 自己的费用
return getPrice() + obj.getPrice();
}
@Override
public String getDsc() {
//输出描述:父类的描述 + 自己的描述
return dsc + " " + getPrice() + " " +obj.getDsc();
}
}
定义具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
具体装饰(ConcreteDecorator)角色1:巧克力 Chocolate
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
setDsc("巧克力");
setPrice(3.0f);
}
}
具体装饰(ConcreteDecorator)角色2:牛奶 Milk
public class Milk extends Decorator{
public Milk(Drink obj) {
super(obj);
setDsc("牛奶");
setPrice(2.0f);
}
}
具体装饰(ConcreteDecorator)角色3:豆浆 Soy
public class Soy extends Decorator{
public Soy(Drink obj) {
super(obj);
setDsc("豆浆");
setPrice(1.5f);
}
}
编写测试类下咖啡订单,测试装饰者模式:
public class coffeeBar {
public static void main(String[] args) {
//一杯美式
Drink order1 = new LongBlack();
System.out.println("订单描述:" + order1.getDsc());
System.out.println("订单费用= " + order1.cost());
//一杯美式 + 一份牛奶
order1 = new Milk(order1);
System.out.println("订单描述:" + order1.getDsc());
System.out.println("订单费用= " + order1.cost());
//一杯美式 + 2份牛奶
order1 = new Milk(order1);
System.out.println("订单描述:" + order1.getDsc());
System.out.println("订单费用= " + order1.cost());
//一杯美式 + 2份牛奶 + 巧克力
order1 = new Chocolate(order1);
System.out.println("订单描述:" + order1.getDsc());
System.out.println("订单费用= " + order1.cost());
}
}
装饰者模式的应用场景
装饰器模式在 Java 中的体现
装饰器模式在 Java语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。
文章浏览阅读3.5k次,点赞7次,收藏41次。但由于输出控制量只有两种状态,使被控参数在两个方向上变化的速率均为最大,因此容易引起反馈回路产生振荡,对自动控制加热炉炉温控制系统会产生十分不利的影响,甚至会因为输出开关的频繁动作而不能满足加热炉炉温控制系统对控制精度的要求。但随着计算机与超大规模集成电路的迅速发展,以现代控制理论和计算机为基础,采用数字控制、显示、A/D与D/A转换,配合执行器与控制阀构成的计算机控制加热炉炉温控制系统,在过程控制过程中得到越来越广泛的应用。由于炉温控制加热炉炉温控制系统的控制对象具有惯性大,连续性的特点。_基于单片机的加热炉炉温控制系统设计
文章浏览阅读2.1k次,点赞2次,收藏4次。上一篇????:Oracle-----为表重命名&数据表删除&闪回技术&修改表结构文章目录1、约束简介2、非空约束(not null、nk)2.1 范例1:使用非空约束2.2 范例2:正确地增加语句2.3 范例3:错误地增加语句3、唯一约束(unique、uk)3.1 范例1:使用唯一约束3.2 范例2:正确地增加语句3.3 范例3:错误地增加语句3.4 范例4:查询user...
文章浏览阅读3.3k次,点赞2次,收藏7次。前言CamVid 数据集是由剑桥大学公开发布的城市道路场景的数据集。CamVid全称:The Cambridge-driving Labeled Video Database,它是第一个具有目标类别语义标签的视频集合。数据集包 括 700 多张精准标注的图片用于强监督学习,可分为训练集、验证集、测试集。同时, 在 CamVid 数据集中通常使用 11 种常用的类别来进行分割精度的评估,分别为:道路 (Road)、交通标志(Symbol)、汽车(Car)、天空(Sky)、行人道(Sidewalk)、电_camvid数据集11类别
文章浏览阅读8.7k次,点赞11次,收藏90次。文章目录一、ESP32 LVGL工程配置1.1从库中下载LVGL代码1.2配置适合ESP32 液晶屏1.3编译下载测试二、GIF图片处理2.1下载gif图片2.2将gif图片按照帧率导出成图片2.lvgl animimg对象实现图片的播放1.3下载测试 注:本博客作为学习笔记,有错误的地方希望指正一、ESP32 LVGL工程配置首先要通过液晶屏显示太空人,我们这里主要有两种方式可以实现,第一种直接使用厂家只带的液晶屏幕驱动去实现图片的显示,另外使用其他的GUI提供的控件去实现,嵌入式常见的GUI挺多_lv_img_declare
文章浏览阅读1.5w次,点赞7次,收藏30次。问题描述:给定一个赋权无向图G=(V,E),每个顶点v∈V都有一个权值w(v)。如果UV,且对任意(u,v)∈E有u∈U或v∈U,就称U为图G的一个顶点覆盖。G的最小权顶点覆盖是指G中所含顶点权之和最小的顶点覆盖。问题解决:用优先队列分支限界方法解最小权顶点覆盖,在算法的搜索的进程中保存当前已构造出的部分解空间树,在算法搜索达到叶节点时,其最优值对应的最优解同时保存下来。优先队列的优先_最小权顶点覆盖
文章浏览阅读517次。首先试了matlab自带的worldmap,感觉画出来的图形不尽如人意,比较杂乱。如下图。查阅了些资料,请教了Liangjing,一致推荐m_map。为了达到想要的效果,这次只要不再偷懒,下载M-Map工具箱(http://www.eos.ubc.ca/~rich/map.html)并进行安装。所幸过程比较顺利,现记录如下,回头把画出的效果图再添上。其他matlab的toolbox安装,也可参考进..._mmap工具包如何安装
文章浏览阅读4.8w次,点赞11次,收藏16次。首先出现的问题是debug@Compileclasspath的问题,经过一波百度之后都说是AS build.gradle版本3.0以上的问题,但是经过一波修改之后并没有什么卵用,并没有解决这个问题,并且出现了新的问题,就是Failed to resolve:.......这个问题了,这面贴下终极解决方案,希望可以帮到你。问题截图:解决方案:在整个工程的build.gradle中添加以..._android failed to resolve: com.github.xiaohaibin:xbanner:1.8.9
文章浏览阅读169次。前言本文主要给大家介绍的是关于Laravel路由模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。备注:本文是基于Laravel 5.4版本的路由模块代码进行分析书写;模块组成下图展示了路由模块中各个文件的关系,并进行简要说明;剖析服务提供者看Laravel模块,首先找ServiceProvider文件,这是模块与IOC容器交互的入口,从这个文件,可以看出该模块提供向..._symfony app('router')->getcurrentrequest()
文章浏览阅读354次。Google Chrome 浏览器 开发者工具 使用教程 12,912 9 3.83 / 5 53.83分(6票)8对于Chrome 浏览器,除了占用内存的缺点,其他都很不错。对于Chrome 浏览器的开发者工具,Jeff 除了Elements、Resources、Network..._开发者使用教程
文章浏览阅读289次。使用maven编译Java项目http://blog.csdn.net/yaya1943/article/details/48464371使用"mvn clean"命令清除编译结果,也就是把编译生成的target文件夹删掉如果你想安装您的项目的JAR文件到本地Maven仓库,那么你应该调用下面语句:mvn install此时,你的项目代码将会经过编译、测试、打..._maven 编译不使用本地依赖包
文章浏览阅读7.6k次,点赞147次,收藏134次。在日常工作中巧用ChatGPT可以帮助我们提高工作效率、创造价值并降低成本。通过合理地利用ChatGPT的功能和应用场景,企业和个人可以更好地实现工作目标、提升竞争力并取得更大的成功。随着人工智能技术的不断进步和发展我们相信巧用ChatGPT将成为未来工作中的一种常态化工具为我们的职业生涯和生活带来更多便利和价值。本书是一本关于数据分析与ChatGPT应用的实用指南,旨在帮助读者了解数据分析的基础知识及利用ChatGPT进行高效的数据处理和分析。_巧用chatgpt快速提高职场晋升力
文章浏览阅读2.7k次。vscode出现10k+更改需要处理_git init 代码有 10k+ 更新