装饰模式的定义与特点

装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

装饰(Decorator)模式的主要优点有:

  • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

其主要缺点是:装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

装饰模式的结构与实现

通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。下面来分析其基本结构和实现方法。

1. 模式的结构

装饰模式主要包含以下角色。

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(Concrete    Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

装饰模式的结构图如图 1 所示。


图1 装饰模式的结构图

2. 模式的实现

装饰模式的实现代码如下:

 
  1. package decorator;
  2. public class DecoratorPattern
  3. {
  4. public static void main(String[] args)
  5. {
  6. Component p=new ConcreteComponent();
  7. p.operation();
  8. System.out.println("---------------------------------");
  9. Component d=new ConcreteDecorator(p);
  10. d.operation();
  11. }
  12. }
  13. //抽象构件角色
  14. interface Component
  15. {
  16. public void operation();
  17. }
  18. //具体构件角色
  19. class ConcreteComponent implements Component
  20. {
  21. public ConcreteComponent()
  22. {
  23. System.out.println("创建具体构件角色");
  24. }
  25. public void operation()
  26. {
  27. System.out.println("调用具体构件角色的方法operation()");
  28. }
  29. }
  30. //抽象装饰角色
  31. class Decorator implements Component
  32. {
  33. private Component component;
  34. public Decorator(Component component)
  35. {
  36. this.component=component;
  37. }
  38. public void operation()
  39. {
  40. component.operation();
  41. }
  42. }
  43. //具体装饰角色
  44. class ConcreteDecorator extends Decorator
  45. {
  46. public ConcreteDecorator(Component component)
  47. {
  48. super(component);
  49. }
  50. public void operation()
  51. {
  52. super.operation();
  53. addedFunction();
  54. }
  55. public void addedFunction()
  56. {
  57. System.out.println("为具体构件角色增加额外的功能addedFunction()");
  58. }
  59. }

程序运行结果如下:

创建具体构件角色
调用具体构件角色的方法operation()
---------------------------------
调用具体构件角色的方法operation()
为具体构件角色增加额外的功能addedFunction()

装饰模式的应用实例

【例1】用装饰模式实现游戏角色“莫莉卡·安斯兰”的变身。

分析:在《恶魔战士》中,游戏角色“莫莉卡·安斯兰”的原身是一个可爱少女,但当她变身时,会变成头顶及背部延伸出蝙蝠状飞翼的女妖,当然她还可以变为穿着漂亮外衣的少女。这些都可用装饰模式来实现,在本实例中的“莫莉卡”原身有 setImage(String t) 方法决定其显示方式,而其 变身“蝙蝠状女妖”和“着装少女”可以用 setChanger() 方法来改变其外观,原身与变身后的效果用 display() 方法来显示(点此下载其原身和变身后的图片),图 2 所示是其结构图。


图2 游戏角色“莫莉卡·安斯兰”的结构图

程序代码如下:

 
  1. package decorator;
  2. import java.awt.*;
  3. import javax.swing.*;
  4. public class MorriganAensland
  5. {
  6. public static void main(String[] args)
  7. {
  8. Morrigan m0=new original();
  9. m0.display();
  10. Morrigan m1=new Succubus(m0);
  11. m1.display();
  12. Morrigan m2=new Girl(m0);
  13. m2.display();
  14. }
  15. }
  16. //抽象构件角色:莫莉卡
  17. interface Morrigan
  18. {
  19. public void display();
  20. }
  21. //具体构件角色:原身
  22. class original extends JFrame implements Morrigan
  23. {
  24. private static final long serialVersionUID = 1L;
  25. private String t="Morrigan0.jpg";
  26. public original()
  27. {
  28. super("《恶魔战士》中的莫莉卡·安斯兰");
  29. }
  30. public void setImage(String t)
  31. {
  32. this.t=t;
  33. }
  34. public void display()
  35. {
  36. this.setLayout(new FlowLayout());
  37. JLabel l1=new JLabel(new ImageIcon("src/decorator/"+t));
  38. this.add(l1);
  39. this.pack();
  40. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  41. this.setVisible(true);
  42. }
  43. }
  44. //抽象装饰角色:变形
  45. class Changer implements Morrigan
  46. {
  47. Morrigan m;
  48. public Changer(Morrigan m)
  49. {
  50. this.m=m;
  51. }
  52. public void display()
  53. {
  54. m.display();
  55. }
  56. }
  57. //具体装饰角色:女妖
  58. class Succubus extends Changer
  59. {
  60. public Succubus(Morrigan m)
  61. {
  62. super(m);
  63. }
  64. public void display()
  65. {
  66. setChanger();
  67. super.display();
  68. }
  69. public void setChanger()
  70. {
  71. ((original) super.m).setImage("Morrigan1.jpg");
  72. }
  73. }
  74. //具体装饰角色:少女
  75. class Girl extends Changer
  76. {
  77. public Girl(Morrigan m)
  78. {
  79. super(m);
  80. }
  81. public void display()
  82. {
  83. setChanger();
  84. super.display();
  85. }
  86. public void setChanger()
  87. {
  88. ((original) super.m).setImage("Morrigan2.jpg");
  89. }
  90. }

程序运行结果如图 3 所示。


图3 游戏角色“莫莉卡·安斯兰”的变身

装饰模式的应用场景

前面讲解了关于装饰模式的结构与特点,下面介绍其适用的应用场景,装饰模式通常在以下几种情况使用。

  • 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

装饰模式在 Java 语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。

下面代码是为 FileReader 增加缓冲区而采用的装饰类 BufferedReader 的例子:

 
  1. BufferedReader in=new BufferedReader(new FileReader("filename.txtn));
  2. String s=in.readLine();

装饰模式的扩展

装饰模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以简化的,如以下两种情况。

(1) 如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件,其结构图如图 4 所示。


图4 只有一个具体构件的装饰模式

(2) 如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并,其结构图如图 5 所示。


图5 只有一个具体装饰的装饰模式

摘至:http://m.biancheng.net/view/1366.html

结构型模式——装饰模式相关推荐

  1. 设计模式-结构型模式-装饰模式

    设计模式-结构型模式-装饰模式 栗子 以成绩单需要家长签字为要求. 成绩单类图 // 抽象成绩单 public abstract class SchoolReport{// 成绩单你的成绩情况publ ...

  2. 结构型模式-装饰模式(扩展系统功能)

    目录 1. 定义 2. 结构 3. 代码实现 4. 透明装饰模式与半透明装饰模式 4.1 透明装饰模式 4.2 半透明装饰模式 5. 注意事项 6. 优缺点 7. 适用场景 8. 个人理解 参考 装饰 ...

  3. 5.4结构型模式—————装饰模式

    装饰模式的定义与特点 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式. 装饰(Decorator)模式 ...

  4. 【设计模式】结构型模式——装饰模式

    文章目录 一.定义 二.问题 三.解决方案 四.实现 五.UML图 六.装饰模式应用场景 七.总结 优点 缺点 八.与其他模式的关系 一.定义 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含 ...

  5. 10 结构型模式-----装饰模式

    模式动机(Decorator Pattern):我们在给一个类进行功能扩展时,总是通过继承或者复合关系,使得一个类具有其他相关类型的功能,继承本身属于静态关联,派生类比较臃肿,使用者也不能控制增加功能 ...

  6. 结构型模式-----装饰模式(decorator)

    1.装饰模式 动态的给一个对象添加一些额外的职责,就增加功能来说Decorator模式相比生成子类更为灵活. 要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例. 实例一: publ ...

  7. C++结构型模式-装饰模式

    1.1 基本概念 装饰器模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,就增加功能来说,装饰器比生成子类实现更为灵活. 装饰器可以在不改变对象本身的基础上给对象增加额外 ...

  8. 设计模式 — 结构型模式 — 装饰模式

    目录 文章目录 目录 装饰模式 应用场景 代码示例 装饰模式 装饰模式,指的是在不需要改变原类和使用继承的情况下,动态地扩展一个对象的功能.它通过创建一个包装对象,也就是 Python 中的装饰器来包 ...

  9. 设计模式09: Decorator 装饰模式(结构型模式)

    Decorator 装饰模式(结构型模式) 子类复子类,子类何其多 加入我们需要为游戏中开发一种坦克,除了不同型号的坦克外,我们还希望在不同场合中为其增加以下一种多种功能:比如红外线夜视功能,比如水路 ...

最新文章

  1. Ensembl数据库下载参考基因组(植物拟南芥)
  2. python列透视_python – 在pandas数据帧中透视列和列值
  3. android 滚动尺画到控件中间,android 刻度尺控件实现
  4. 【LOJ】#2887. 「APIO2015」雅加达的摩天楼 Jakarta Skyscrapers
  5. npm常用命令(扩展中...)
  6. SpringBoot中常见注解
  7. [Ext JS 7]基于NPM的开发
  8. 二维码扫描ZXing简化
  9. webpack 生产环境下插件用途
  10. Python sys.path、sys.modules模块介绍
  11. PyTorch Bert文本分类
  12. 测试笔记本续航的软件,【教程向】如果给笔记本降温及延长续航
  13. 文献阅读笔记:北极气溶胶与气候
  14. 加ing形式的单词有哪些_动词ing形式变化规则有哪些
  15. 思考(六十四):游戏中的角色ID问题
  16. 外星人笔记本计算机在哪里,笔记本电脑没声音,详细教您外星人笔记本没声音如何解决...
  17. 常用的web服务器软件有哪些
  18. OCR手写文字怎么识别
  19. 【web前端特效源码】使用HTML5+CSS3制作一个会动的音频loading加载动画效果~~适合初学者~超简单~ |前端开发|IT编程
  20. chosen插件--简单快速的理解

热门文章

  1. 华为AirEngine 9700S AC控制器上传 license文件出现不存在上传失败
  2. wpf ComboBox使用Dictionary来绑定数据
  3. .net mysql transactionscope_TransactionScope事务处理方法介绍及.NET Core中的注意事项
  4. 【JS】html页面生成水印
  5. 大数据实践-Kyuubi
  6. 小米路由器 php7,小米路由器好不好用?看完这个评测你就懂了!
  7. 电脑计算机怎么没有桌面显示器,电脑显示器没有图标怎么办
  8. JAVA初记笔记面向对象18(4)
  9. 使用Windbg排查线程死锁引起的连不上服务器问题
  10. android中下拉菜单的制作(详解)