Java结构性设计模式中的装饰器模式介绍使用
作者:丨Jack_Chen丨 发布时间:2022-04-08 06:30:00
装饰器模式
概述
装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),属于结构型模式。
它是指在不改变原有对象的基础之上,允许向一个现有的对象添加新的功能,同时又不改变其结构,作为现有的类的一个包装。
这种模式创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
提供了比继承更有单性的替代方案,进行扩展原有对象的功能。
装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态地扩展类的功能。
装饰器模式主要用于诱明且动态地扩展类的功能。
实现原理
让装饰器实现被包装类相同的接口,使得装饰器与被扩展类类型一致,并在构造函数中传入该接口对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能。
由于装饰器与被包装类属于同一类型,且构造函数的参数为其实现接口类,因此装饰器模式具备嵌套扩展功能,因此就能使用装饰器模式一层层的对最底层被包装类进行功能扩展。
在JDK中,IO相关包下大量使用装饰器模式,如BufferedReader、InputStream、OutputStream等类
主要角色
装饰器模式主要包含4种角色
1.抽象组件(Component)
抽象组件可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为。
2.具体组件(ConcreteComponent)
具体组件实现/继承抽象组件的一个具体对象,即被装饰对象。
3.抽象装饰器(Decorator)
通用的装饰具体组件的装饰器,其内部必然有一个属性指向抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个抽象组件,这是强制的通用行为。
如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么可以直接省略该类,而直接实现一个具体装饰器即可。
4.具体装饰器(ConcreteDecorator)
抽象装饰器的具体实现类,理论上,每个具体组件都扩展了抽象组件对象的一种功能。
应用场景
1.用于扩展一个类的功能或给一个类添加附加职责。
2.动态的给一个对象添加功能,这些功能可以再动态的澈销。
3.需要为一批的兄弟类进行改装或加装功能。
优缺点
优点:
1.装饰器是继承的补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
2.装饰器完全遵守开闭原则。
缺点:
1.会出现更多的代码,更多的类,增加程序复杂性。
2.通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。
3.动态装饰时,多层装饰时会更复杂。
装饰器模式的基本使用
创建抽象组件
创建Phone抽象类
public abstract class Phone {
public abstract String call();
public abstract double price();
}
具体组件
创建最基本具有打电话功能的手机
public class BasePhone extends Phone {
@Override
public String call() {
return "BasePhone call";
}
@Override
public double price() {
return 0.1;
}
}
抽象装饰器
创建一个抽象装饰器来扩展该只具备基本功能的手机
public abstract class PhoneDecorator extends Phone {
private Phone phone;
public PhoneDecorator(Phone phone) {
this.phone = phone;
}
@Override
public String call() {
return phone.call();
}
@Override
public double price() {
return phone.price();
}
/**
* 扩展功能
*/
public abstract void sendMsg();
}
具体装饰器
public class SatellitePhoneDecorator extends PhoneDecorator{
public SatellitePhoneDecorator(Phone phone) {
super(phone);
}
public void sendMsg() {
System.out.println("PhoneCallDecorator sendMsg");
}
@Override
public String call() {
return "SatellitePhone call";
}
@Override
public double price() {
return super.price()+100;
}
}
客户端调用
public static void main(String[] args) {
// 创建需要被装饰的原始对象(即要被装饰的对象)
Phone phone = new BasePhone();
System.out.println("使用: "+phone.call()+" 方式打电话,每分钟单价:" + phone.price());
// 给对象透明的增加额外功能并调用
PhoneDecorator phoneDecorator = new SatellitePhoneDecorator(phone);
System.out.println("使用: "+phoneDecorator.call()+" 方式打电话,每分钟单价:" + phoneDecorator.price());
// 装饰器也可以装饰具体的装饰对象,相当于给对象在增加的功能基础上在添加功能,这里体现在单价100.1基础上再+100
PhoneDecorator satellitePhoneDecorator = new SatellitePhoneDecorator(phoneDecorator);
System.out.println("使用: "+satellitePhoneDecorator.call()+" 方式打电话,每分钟单价:" + satellitePhoneDecorator.price());
satellitePhoneDecorator.sendMsg();
}
使用: BasePhone call 方式打电话,每分钟单价:0.1
使用: SatellitePhone call 方式打电话,每分钟单价:100.1
使用: SatellitePhone call 方式打电话,每分钟单价:200.1
PhoneCallDecorator sendMsg
来源:https://blog.csdn.net/qq_38628046/article/details/126131404


猜你喜欢
- 1:定义一个自己的父级容器,让它继承自一个布局(LinearLayout、RelativeLayout都可以)public class Si
- 文件的上传及下载功能是开发人员在日常应用及编程开发中经常会遇到的。正好最近开发需要用到此功能,虽然本人是 Android 开发人员,但还是业
- 利用 Spring 工厂加载机制,实例化 ApplicationListener 实现类,并排序对象集合创建应用事件 * 创建类实现接口Ap
- 正文:相关术语翻译说明:Mark,标记;Sweep,清除;Compact,整理; 也有人翻译为压缩,译者认为GC时不存在压缩这回事。Copy
- Mapper类中存在名称相同的方法重载报错项目场景官网项目开发问题描述Mapper类中存在名称相同的方法重载报错为了省事,直接在mapper
- 1.Java Io流的概念,分类,类图。1.1 Java Io流的概念java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操
- 1. 查找系统中坏味道的异常处理代码在上篇文章杂谈异常处理try-catch-finally中主要详细介绍了C#异常处理的概念,
- 前言在上一章节Spring和Mybatis整合的原理详解中有写到Spring和MyBatis整合时用到的Bean扫描是Spring本身提供的
- 目录Bitmap类BitmapData类参考:Bitmap类Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组
- 一、了解面向对象1、概念基本理解:1)、一个个体可以看做是一个对象,例如:人这个个体;2)、有共同属性的一类作为一个个体,例如:学生、白领、
- 只需要调用该类的一个方法createNewFile(),但是在实际操作中需要注意一些事项,如判断文件是否存在,以及如何向新建文件中写入数据等
- 1 起因在实际业务开发中, 我们经常会遇到需要临时创建一个数组的情况, 今天我们就来讲一下Java中ArrayList初始化的方法2 解决方
- Java 利用poi把数据库中数据导入Excel效果:使用时先把poi包导入工程的path,注意只需要导入poi包即可,下载后有三个jar包
- /** * 进行BigDecimal对象的加减乘除,四舍五入等运算的工具类 * * @author Marydon * @createTi
- 前 言终于来到下篇了,通过上篇,和中篇,我们了解了linq的基本语句,对应linq我们又了解到lambda表达式,静态扩展方法,以及linq
- 类加载是什么把磁盘中的java文件加载到内存中的过程叫做类加载当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把
- Spring是什么?Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其
- 表述在一次服务更新后发现每天凌晨0点3秒服务准时挂,开始的时候认为是maven依赖中存在system.exit(3)类似这样的代码,但是我想
- 在平时的开发中,我们会经常遇到这样一个需求,要在页面通过一个『导出』按钮把查询出的数据导出到 Excel 表格中。本文即为实现上述需求的一个
- 首先介绍下JSON的定义,JSON是JavaScript Object Notation的缩写。一种轻量级的数据交换格式,具有良好的可读和便