【结构型模式】装饰器模式

​一、装饰器模式概述

        装饰器模式(装饰者模式)定义装饰器模式动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性地替代方案。(对象结构型模型)通俗点来说:动态的给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。

  • 利用继承来达到“类型匹配”
    • 1.装饰者与被装饰对象有相同地超类型;
    • 2.可以用一个或多个装饰者包装一个对象;
    • 3.既然装饰者与被装饰对象有相同地超类型,所以在任何需要原始对象(被包装地)的场合,可以用装饰过的兑现代替它;
    • 4.装饰者可以在所委托被装饰者的行为之前与/之后,加上自己的行为,以达到特定的目的;
    • 5.对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
  •  装饰模式分析
    • 1.可以在不改变一个对象本身功能的基础上给对象增加额外的新行为;
    • 2.是一种用于替代继承的技术,它通过一种无需有定义子类的方式给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系;
    • 3.引入了装饰类,在装饰类中既可以调用装饰的原有类的方法,还可以增加新的方法,以扩展原有类的功能。

        ​透明装饰模式与半透明装饰模式

  • 半透明装饰模式
    • 1.可以给系统带来更多的灵活性,设计相对简单,使用起来也方便;
    • 2.客户端使用具体装饰类型来定义装饰后的对象,因此可以单独调用addedBehavior()方法;
    • 3.最大的缺点在于不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象;
    • 4.用具体装饰定义装饰之后的对象,而具体构件使用抽象构件类型来定义;
    • 5.对于客户而言,具体构件类型无须关心,是透明的;但是具体装饰类型必须指定,这并不是透明的。
  • 透明装饰模式
    • 1.要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型;
    • 2.对客户端而言,具体构件对象和具体装饰对象没有任何区别;
    • 3.可以让客户透明地使用装饰之前地对象和装饰之后地对象,无须关心他们的区别;
    • 4.可以对一个已装饰过地对象进行多次装饰,得到更多复杂、功能更为强大的对象;
    • 5.无法在客户端单独调用新增addedBehavior()方法
  • 适用环境
    • 1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责;
    • 2.当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式

        装饰者模式优缺点

  • 优点
    • 1.对于扩展一个对象功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加;
    • 2.可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为;
    • 3.可以对一个对象进行多次装饰;
    • 4.具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,且原有类库代码无需变化,符合开闭原则。
  • 缺点
    • 1.使用装饰模式进行系统设计时将产生很多小对象,大量对象对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能;
    • 2.比继承更加易于出错,排错也更困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

二、代码实现

        结构包含四个角色:

  • 抽象构件(Component)
  • 具体构件(ConcreteComponent)
  • 抽象装饰类(Decorator)
  • 具体装饰类(ConcreteDecorator)
         2.1 星巴兹咖啡

        2.1.1 抽象构件(抽象基类饮料Beverage)
package decorator.dec;
//抽象构件:饮料
public abstract class Beverage {String description = "Unknown Noodle";int size;//小杯TALL、中杯GRANDE、大杯WENTIpublic final static int TALL=1;public final static int GRANDE=2;public final static int WENTI=3;public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public abstract double cost();
}
        2.1.2 具体构件(基于饮料的咖啡:DarkRoast、Decaf、Espressio、HouseBlend)
package decorator.dec;
//意大利浓咖啡
public class DarkRoast extends Beverage{public DarkRoast() {description = "DarkRoast";}public double cost() {return 3;}
}
package decorator.dec;
//不加咖啡因的咖啡
public class Decaf extends Beverage{public Decaf() {description = "Decaf";}public double cost() {return 2;}
}
package decorator.dec;
//意式浓缩咖啡
public class Espressio extends Beverage{public Espressio() {description = "Espressio";}public double cost() {return 2.5;}
}
package decorator.dec;
//混合咖啡
public class HouseBlend extends Beverage{public HouseBlend() {description = "HouseBlend";}public double cost() {return 1.5;}
}
        2.1.3 抽象装饰类(抽象装饰类CondimentDecorator)
package decorator.dec;
//抽象装饰类:描述->>配料继承父类,附加在父类上
public abstract class CondimentDecorator extends Beverage{Beverage beverage;public abstract String getDescription();
}
        2.1.4 具体装饰类(添加在咖啡上的牛奶milk、抹茶Mocha、豆奶Soy、咖啡的大小Size、搅拌Whip)
package decorator.dec;
//牛奶
public class milk extends CondimentDecorator{public milk(Beverage beverage) {this.beverage=beverage;}public String getDescription() {return beverage.getDescription() + ",Milk";}public double cost() {return 1+beverage.cost();}
}
package decorator.dec;
//抹茶
public class Mocha extends CondimentDecorator {public Mocha(Beverage beverage) {this.beverage=beverage;}@Overridepublic String getDescription() {// TODO 自动生成的方法存根return beverage.getDescription() + ",Mocha";}public double cost() {return 1+beverage.cost();}}
package decorator.dec;
//豆奶
public class Soy extends CondimentDecorator {public Soy(Beverage beverage) {this.beverage=beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ",Soy";}public double cost() {return 1+beverage.cost();}
}
package decorator.dec;
//大小
public class Size extends CondimentDecorator {public Size(Beverage beverage,int size) {this.beverage = beverage;this.size=size;}@Overridepublic String getDescription() {// TODO 自动生成的方法存根if(size == beverage.TALL) {return beverage.getDescription() + ",小杯";}else if(size == beverage.GRANDE) {return beverage.getDescription() + ",中杯";}else if(size == beverage.WENTI) {return beverage.getDescription() + ",大杯";}return null;}@Overridepublic double cost() {double cost = beverage.cost();if(size == beverage.TALL) {cost += 0.1;}else if(size == beverage.GRANDE) {cost +=0.2;}else if(size == beverage.WENTI) {cost +=0.3;}return cost;}}
package decorator.dec;
//搅拌
public class Whip extends CondimentDecorator {//Noodle beverage;public Whip(Beverage beverage) {this.beverage=beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ",Whip";}public double cost() {return 1+beverage.cost();}
}
        2.1.5  main方法实现装饰者模式
package decorator.dec;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根Beverage beverage1 =new Mocha(new milk(new DarkRoast()));System.out.println(beverage1.getDescription()+" 合计$"+beverage1.cost());Beverage beverage2 =new Mocha(new milk(new DarkRoast()));Beverage beverage3 =new Size(new Mocha(new milk(new DarkRoast())),2);Beverage size = new Size(beverage2,2);System.out.println(size.getDescription()+" 合计$"+size.cost());}
}
        2.1.6 UML图

        2.2 窗口显示
        2.2.1 抽象构件(抽象基类:显示构件Component)
package decorator.visualCompanent;
//显示构件
public abstract class Component {public abstract void display();
}
        2.2.2 具体构件(列表框、文本框、窗体)
package decorator.visualCompanent;public class ListBox extends Component {@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("显示列表框!");}}
package decorator.visualCompanent;public class TextBox extends Component {@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("显示文本框!");}}
package decorator.visualCompanent;public class Window extends Component {@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("显示窗体!");}}
         2.2.3 抽象装饰类(ComponentDecorator)
package decorator.visualCompanent;public class ComponentDecorator extends Component{private Component component;//维持对抽象构件类型对象的引用//注入抽象构件类型的对象public ComponentDecorator(Component component) {this.component = component;}public void display() {component.display();}
}
          2.2.4 具体装饰类(增加新的构件:黑色边框和滚动条)
package decorator.visualCompanent;public class BlackBorderDecorator extends ComponentDecorator {public BlackBorderDecorator(Component component) {super(component);}public void display() {// TODO 自动生成的方法存根this.setBlackBorder();super.display();}public void setBlackBorder() {System.out.println("为构件增加黑色边框!");}
}
package decorator.visualCompanent;public class ScrollBarDecorator extends ComponentDecorator {public ScrollBarDecorator(Component component) {super(component);}public void display() {// TODO 自动生成的方法存根this.setScrollBar();super.display();}public void setScrollBar() {System.out.println("为构件增加滚动条!");}}
        2.2.5 main方法实现装饰者模式
package decorator.visualCompanent;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根//使用抽象构件定义全部对象Component component,componentSB,componentBB;component = new Window(); //创建具体对象//创建装饰后的构件对象componentSB = new ScrollBarDecorator(component);//将装饰了一次的对象componentBB = new BlackBorderDecorator(componentSB);componentBB.display();}}
        2.2.6 UML图

三、代码结构图

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

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

相关文章

淘宝购物更智能:taobao.item_search API接口实现关键字精准匹配

随着电子商务的飞速发展,淘宝作为中国最大的网络购物平台之一,为亿万消费者提供了便捷、丰富的购物体验。然而,在海量商品中快速找到符合自己需求的商品,一直是消费者面临的挑战。为了提升购物体验,淘宝开放平台提供了…

【JS】js数字转k、w结尾 | 1000 = 1k

问题 数字转k、w结尾 如&#xff1a;10001k 100001w 码 /*** 数字转k,w* param {Number} num * returns String*/ const numberTokw num > {if (num < 1000) return numlet endStr w,numVal 10000;if (num > 999 && num < 10000) {endStr knumVal …

使用python socket搭建Client测试平台

目录 概述 1 背景 2 Client功能实现 2.1 何谓Client 2.2 代码功能介绍 2.3 代码实现 2.3.1 代码介绍 2.3.2 代码内容 3 测试 3.1 PC上创建Server 3.2 同一台PC上运行Client 3.2.1 建立连接 3.2.2 测试数据交互 3.3 Linux 环境下运行Client 3.3.1 建立连接 3.3.…

ElasticSearch实战之项目搜索高亮

文章目录 1. 前情配置2、数据操作2.1 操作API2.2 数据入库 3. 高亮搜索3.1 方法封装3.2 高亮搜索 1. 前情配置 为满足ElasticSearch可在项目中实现搜索高亮&#xff0c;我们需要先做一些前情配置 导入ElasticSearch依赖 <dependency><groupId>org.springframewor…

Linux网络实战(三)- Samba服务器搭建

Linux网络实战&#xff08;三&#xff09;- Samba服务器搭建 1 安装Samba服务软件编程要求输出输入 2 Samba服务器启动/关闭编程要求输出输入 3 Samba客户端编程要求输出输入 1 安装Samba服务软件 编程要求 本关任务是学会如何在线安装samba软件。 具体编程要求如下&#xf…

两个表归并为有序表

先排序&#xff0c;在逐个比较插入&#xff0c;最坏时间复杂度为表1长度表2长度-1 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h>typedef struct List {int* elem;//存储空间地址int length;//表长 }List;void sortList(List* p, int …

第3章 决策树

决策树经常处理分类问题&#xff0c;近来的调查表明决策树也是经常使用的数据挖掘算法。 决策树的流程图&#xff1a; 长方形代表判断模块(decision block)&#xff0c;椭圆形代表中止模块(terminating block),表示已经得出结论&#xff0c;可以中止运行。 从判断模块引出左右箭…

EPSON晶振应用到汽车电子产品上的型号有哪些?

EPSON品牌应用在汽车电子产品上的晶振.&#xff0c;当然也少不了晶振可能最熟悉的就是32.768K系列和26MHZGPS晶振用的多。 在汽车里每一个部件都应有的不一样,甚至多次使用到同一尺寸,不同频率的晶振.爱普生品牌晶振型号就有几百种,很容易混淆,要想记住汽车里所应用到的不是件…

模型实战(19)之 从头搭建yolov9环境+tensorrt部署+CUDA前处理 -> 实现目标检测

从头搭建yolov9环境+tensorrt部署实现目标检测 yolov9虚拟环境搭建实现训练、推理与导出导出onnx并转为tensorrt模型Python\C++ - trt实现推理,CUDA实现图像前处理文中将给出详细实现源码python、C++效果如下:output_video_1 1. 搭建环境 拉去官方代码根据配置下载虚拟环境所…

【JAVA】检查两个字符串是否一致的几种方法

1.使用equals()方法&#xff1a; String str1 "Hello"; String str2 "Hello";boolean areEqual str1.equals(str2); // true 注意&#xff0c;如果有可能遇到null值&#xff0c;使用Objects.equals()方法更为安全&#xff0c;因为它可以避免空指针异常…

B树(B-tree)

B树(B-tree) B树(B-tree)是一种自平衡的多路查找树&#xff0c;主要用于磁盘或其他直接存取的辅助存储设备 B树能够保持数据有序&#xff0c;并允许在对数时间内完成查找、插入及删除等操作 这种数据结构常被应用在数据库和文件系统的实现上 B树的特点包括&#xff1a; B树为…

oracle快速定位数据库瓶颈

oracle快速定位数据库瓶颈 –数据库巡检或性能优化方法各异&#xff0c;但首要的是要发现数据库性能瓶颈&#xff0c;系统自带的statspack,或awr太耗时. 查询数据库等待事件top10,关注前前几个等待事件&#xff0c;关注前三个等待事件是否有因果或关联关系–oracle 9i select…

学习空间转换-3D转换

1.什么是空间转换&#xff1f; 使用的是transform属性实现元素在空间内的位移&#xff0c;旋转&#xff0c;缩放等效果。 空间&#xff1a;是从坐标轴角度定义的。x,y,z三条坐标轴构成的一个立体空间&#xff0c;Z轴位置与视线方向相同。 所以空间转换也被叫做3D转换 语法&a…

PICkit 3 v3.10中的 Device Family 识别不到芯片

1&#xff1a;现象描述 在使用 PICkit3烧写hex文件的时候&#xff0c;Device Family只有默认芯片&#xff0c;识别不到当前使用的芯片&#xff0c;导致报错“Device Error - hex file not loaded”&#xff0c;我当前使用的是 PIC16F1826芯片&#xff0c;默认不支持&#xff1…

快速开发部署平台Replit

Replit 是可以快速搭建开发、部署环境的平台。能够快速将原型进行部署&#xff0c;代码编辑器支持协同开发&#xff0c;他的在线编辑器做的不错&#xff0c;相当于云上提供了一个 vscode&#xff0c;代码实时更新。Replit 底层是基于容器技术的&#xff0c;可以安全的隔离多个用…

html、css、QQ音乐移动端静态页面,资源免费分享,可作为参考,提供InsCode在线运行演示

CSDN将我上传的免费资源私自变成VIP专享资源&#xff0c;且作为作者的我不可修改为免费资源&#xff0c;不可删除&#xff0c;寻找客服无果&#xff0c;很愤怒&#xff0c;&#xff08;我发布免费资源就是希望大家能免费一起用、一起学习&#xff09;&#xff0c;接下来继续寻找…

Yonbuilder参考

发布移动插件 https://developer.yonyou.com/cloud/moduleStore/publishPlugin Android自定义插件打包 社区问答 https://community.yonyou.com/forum.php?modviewthread&tid232830&searchLogId605932 MarkDown指令使用 https://blog.csdn.net/qq_25821067/article/de…

深入了解 Gitea:轻量级的自托管 Git 服务

在软件开发和团队协作中&#xff0c;版本控制系统是不可或缺的工具。Git 是目前最流行的分布式版本控制系统之一&#xff0c;而 Gitea 则是基于 Git 的一个轻量级、自托管的 Git 服务。本文将介绍 Gitea 的特点、功能和使用方法&#xff0c;帮助读者更好地了解和使用这一工具。…

分享|网红阳哥介绍的项目能赚钱吗?具体有哪些项目?

在当今的互联网时代&#xff0c;网红的影响力不容小觑&#xff0c;他们通过分享自己的经验和见解&#xff0c;往往能带动一股潮流或引领一种趋势。其中&#xff0c;网红阳哥以其独到的眼光和丰富的经验&#xff0c;分享了一系列赚钱项目&#xff0c;引起了广泛关注。那么&#…

Linux 远程联机服务(一)- Telnet服务器

Linux 远程联机服务&#xff08;一&#xff09;- Telnet服务器 第1关&#xff1a;安装Telnet编程要求预期输出输入 第2关&#xff1a;Telnet服务器启动/关闭编程要求预期输出输入 第3关&#xff1a;Telnet远程登录编程要求预期输出输入 第1关&#xff1a;安装Telnet 编程要求 …