【设计模式】装饰器模式( Decorator Pattern)
创始人
2024-02-15 11:45:23

装饰器模式属于结构型模式,主要解决当系统需要添加新功能,需要向旧类中不断添加新的属性和方法,从而导致整个类的复杂度不断增长的问题。假如新加的代码仅仅是为了满足特定场景下才会执行的需要,那么就没必要全部写在主类中,此时就可以使用装饰模式来解决,把要装饰的代码写在新加的类中,在需要的时候动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

文章目录

  • 装饰器模式的介绍
    • 优点
    • 缺点
    • 应用场景
  • 装饰器模式的使用
    • 类图
      • 装饰器中存在四个角色
    • 实现方法
      • 第一步,编写具体构建角色(机甲类)
      • 第二步,编写抽象装饰角色(外设类)
      • 第三步,编写具体装饰角色(钛合金装甲等模块)
      • 第四步,编写测试类测试
  • 本文参考


装饰器模式的介绍

​ 装饰器(Decorator)模式也可叫包装模式(Wrapper Pattern) ,是为已有功能动态添加更多功能的一种方式。装饰器通过新建装饰类,用来包装原有的类,在保证原有类结构完整的情况下添加新功能。此模式将原有类当做组件,或者为原有类新建一个抽象类当做组件接口,原有类和装饰类通过继承该抽象类来实现关联。当需要使用装饰功能时只需要让装饰类包装原有类的对象即可完成装饰。

优点

  • 装饰器是继承的有力补充,它比继承灵活,在不改变原有对象的情况下,能够动态的给一个对象扩展功能
  • 有效的将类的核心功能和装饰功能分离,去除相关类中重复的装饰逻辑
  • 装饰类和被装饰类解耦,可以独立修改扩展
  • 通过使用不同装饰类与被装饰类组合,实现不同的功能实现
  • 符合开闭原则

缺点

  • 装饰类通过添加新的子类来实现新的功能,到后期可能会出现大量装饰子类,增加复杂性
  • 多层装饰会导致程序层次更复杂

应用场景

  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时

  • 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类

  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现

  • 在Java IO中 OutputStream 就具备多个装饰子类,如 ByteArrayOutputStreamObjectOutputStreamFileOutputStream等都是对输出流功能的扩展。



装饰器模式的使用

例子:可恶的怪物正在践踏我们的家园!万幸科学家们已经完成了对机甲(被装饰类)的研制工作,工程师们也为机甲设计了多套强大的扩展装甲(装饰类),是时候组装我们的最强机甲了,把那些怪物溺死在太平洋吧!

类图

装饰器中存在四个角色

  • 抽象构件(Component)角色:该角色定义一个抽象接口以规范准备接收额外责任的对象,但我的例子中因为只有一个机甲,所以不需要设置该角色

  • 具体构件(Concrete Component)角色:实现抽象构件,通过装饰该角色来为其添加一些额外的职责,对应上方的机甲类

  • 抽象装饰(Decorator)角色:该角色继承抽象构件,为抽象类,类中持有具体构件的实例,以此达到通过其子类扩展具体构件职责的功能,对应上方外设类

  • 具体装饰(Concrete Decorator)角色:实现抽象装饰角色的相关方法,以此给具体构件对象添加附加的责任


实现方法


第一步,编写具体构建角色(机甲类)

机甲类

package 设计模式.结构型模式.装饰器模式;/*** 具体构件角色,因为本案例只有一个具体构件,所以不需要设置抽象构件来约束构件角色*/
public class 机甲类 {public void 展示(){System.out.println("机甲开始组装……组装完毕!");}
}

第二步,编写抽象装饰角色(外设类)

外设类

package 设计模式.结构型模式.装饰器模式;/*** 抽象装饰角色,约束具体装饰类的方法*/
public abstract class 外设类 extends 机甲类 {protected 机甲类 待装机甲;public 外设类(机甲类 待装机甲){// 持有被装饰类,通过聚合关系达到被装饰类与装饰类的组合this.待装机甲 = 待装机甲;}// 规定具体装饰类通过该方法来对被装饰类的功能进行扩展public abstract void 展示();
}

第三步,编写具体装饰角色(钛合金装甲等模块)

钛合金装甲模块

package 设计模式.结构型模式.装饰器模式;public class 钛合金装甲模块 extends 外设类 {public 钛合金装甲模块(机甲类 待装机甲) {super(待装机甲);}@Overridepublic void 展示() {// 执行装饰类附加的功能System.out.println("装备【钛合金装甲模块】");// 最后执行被装饰类的功能待装机甲.展示();}
}

微型核能续航模块

package 设计模式.结构型模式.装饰器模式;public class 微型核能续航模块 extends 外设类 {public 微型核能续航模块(机甲类 待装机甲) {super(待装机甲);}@Overridepublic void 展示() {// 执行装饰类附加的功能System.out.println("装备【微型核能续航模块】");// 最后执行被装饰类的功能待装机甲.展示();}
}

自动追踪导弹模块

package 设计模式.结构型模式.装饰器模式;public class 自动追踪导弹模块 extends 外设类 {public 自动追踪导弹模块(机甲类 待装机甲) {super(待装机甲);}@Overridepublic void 展示() {// 执行装饰类附加的功能System.out.println("装备【自动追踪导弹模块】");// 最后执行被装饰类的功能待装机甲.展示();}
}

多功能组合臂模块

package 设计模式.结构型模式.装饰器模式;public class 多功能组合臂模块 extends 外设类 {public 多功能组合臂模块(机甲类 待装机甲) {super(待装机甲);}@Overridepublic void 展示() {// 执行装饰类附加的功能System.out.println("装备【多功能组合臂模块】");// 最后执行被装饰类的功能待装机甲.展示();}
}

重装弱重力推进器

package 设计模式.结构型模式.装饰器模式;public class 重装弱重力推进器 extends 外设类 {public 重装弱重力推进器(机甲类 待装机甲) {super(待装机甲);}@Overridepublic void 展示() {// 执行装饰类附加的功能System.out.println("装备【重装弱重力推进器】");// 最后执行被装饰类的功能待装机甲.展示();}
}


第四步,编写测试类测试

测试类

package 设计模式.结构型模式.装饰器模式;public class 测试类 {public static void main(String[] args) {// 开始组装第一台机甲System.out.println("开始组装第一台机甲:爱国机甲");机甲类 爱国机甲 = new 机甲类();// 对爱国机甲进行装饰爱国机甲 = new 自动追踪导弹模块(爱国机甲);爱国机甲 = new 微型核能续航模块(爱国机甲);爱国机甲 = new 钛合金装甲模块(爱国机甲);// 展示爱国机甲爱国机甲.展示();System.out.println("——————————————————————————————————");// 组装第二台机甲,对被装饰类进行不同的装饰System.out.println("开始组装第二台机甲:友善机甲");机甲类 友善机甲 = new 机甲类();// 对友善机甲进行装饰友善机甲 = new 重装弱重力推进器(友善机甲);友善机甲 = new 钛合金装甲模块(友善机甲);友善机甲 = new 多功能组合臂模块(友善机甲);友善机甲 = new 微型核能续航模块(友善机甲);友善机甲 = new 自动追踪导弹模块(友善机甲);// 展示友善机甲友善机甲.展示();}
}

测试结果

开始组装第一台机甲:爱国机甲
装备【钛合金装甲模块】
装备【微型核能续航模块】
装备【自动追踪导弹模块】
机甲开始组装……组装完毕!
——————————————————————————————————
开始组装第二台机甲:友善机甲
装备【自动追踪导弹模块】
装备【微型核能续航模块】
装备【多功能组合臂模块】
装备【钛合金装甲模块】
装备【重装弱重力推进器】
机甲开始组装……组装完毕!Process finished with exit code 0

image-20221125194326790




本文参考

《大话设置模式》 作者:程杰

菜鸟教程 装饰器模式

设计模式学习笔记(十)装饰器模式及其应用

24 设计模式——装饰器模式(装饰设计模式)详解

设计模式之装饰器模式详解

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...