【笔记整理】图解设计模式 | 导航


定义

  • 不断地为对象添加装饰的设计模式被称为Decorator模式,其中Decorator指的是“装饰物”。

Decorator模式中的登场角色

  • Component(API,抽象

Component角色定义了公共的接口(API)。

  • ConcreteComponent(被装饰物)

该角色是实现了Component角色所定义的接口(API)的具体类。

  • Decorator(装饰物,抽象

该角色具有与Component角色相同的接口(API)。在它内部保存了被装饰对象——Component角色。Decorator角色知道自己要装饰的对象。

  • ConcreteDecorator(具体的装饰物)

该角色是具体的Decorator角色。


Decorator模式的类图

关键点:

  • 装饰物是API公共接口的子类。
  • 装饰物中有一个被装饰物的实例,并以构造函数形式进行初始化。
  • 方法执行顺序:首先执行装饰物的方法,再执行被装饰物的方法,以达到装饰的目的。

拓展思路的要点

  • 接口(API)的透明性

在Decorator模式中,装饰边框与被装饰物具有一致性。表示装饰边框的类是表示被装饰物的类的子类,体现了它们之间的一致性,它们具有相同的接口(API)。

这样,即使被装饰物被边框装饰起来了,接口(API)也不会被隐藏起来。其他类依然可以调用接口的方法。这就是接口(API)的透明性

得益于接口(API)的透明性,Decorator模式中也形成了类似于Composite模式中的递归结构。也就是说,装饰边框里面的“被装饰物”实际上又是别的物体的“装饰边框”。就像是剥洋葱时以为洋葱心要出来了,结果却发现还是皮。

不过,Decorator模式虽然与Composite模式一样,都具有递归结构,但是它们的使用目的不同。Decorator模式的主要目的是通过添加装饰物来增加对象的功能。Composite模式的目的拥有关系(Composite模式是树形结构,Decorator模式俄罗斯套娃。)。

  • 在不改变被装饰物的前提下增加功能

在Decorator模式中,装饰边框与被装饰物具有相同的接口(API)。虽然接口(API)是相同的,但是越装饰,功能则越多。这样,我们就实现了不修改被装饰的类即可增加功能

Decorator模式使用了委托。对“装饰边框”提出的要求(调用装饰边框的方法)会被转交(委托)给“被装饰物”去处理。

  • 可以动态地增加功能

Decorator模式中用到了委托,它使类之间形成了弱关联关系。因此,不用改变框架代码,就可以生成一个与其他对象具有不同关系的新对象。

  • 只需要一些装饰物即可添加许多功能

可以将一些功能非常简单的装饰边框,自由组合成为新的对象。

  • Java.io包与Decorator模式

除了java.io包以外,javax.swing.border包中也使用了Decorator模式,提供了可以为界面中的控件比那家装饰边框的类。


相关的设计模式

  • Adapter模式(第2章)

Decorator模式可以在不改变被装饰物的接口(API)的前提下,为被装饰物添加边框(透明性)。

Adapter模式用于适配两个不同的接口(API)。

  • Stragety模式(第10章)

Decorator模式可以像改变被装饰物的边框或是被装饰物添加多重边框那样,来增加类的功能。

Stragety模式通过整体地替换算法来改变类的功能。


延伸阅读:继承和委托中的一致性

  • 继承——父类和子类的一致性
  • 委托——自己和被委托对象的一致性

代码

  • Component(API)
public abstract class Display {public abstract int getColumns(); // 获取横向字符数 <-- -->public abstract int getRows(); // 获取纵向行数public abstract String getRowText(int row); // 获取第row行的字符串public final void show() { // 全部显示for (int i = 0; i < getRows(); i++) {System.out.println(getRowText(i));}}
}
  • ConcreteComponent(被装饰物)
/*** 显示单行字符串*/
public class StringDisplay extends Display {private String string; // 要显示的字符串public StringDisplay(String string) { // 通过参数传入要显示的字符串this.string = string;}@Overridepublic int getColumns() { // 字符数return string.getBytes().length;}@Overridepublic int getRows() { // 行数是1return 1;}@Overridepublic String getRowText(int row) { // 仅当row为0时返回值if (0 == row) {return string;}return null;}}
  • Decorator(装饰物)
public abstract class Border extends Display {protected Display display;public Border(Display display) {this.display = display;}}
  • ConcreteDecorator(具体的装饰物)
public class SideBorder extends Border {private char borderChar;// 表示装饰边框的字符public SideBorder(Display display, char ch) { // 通过构造函数执行Display和装饰边框字符super(display);borderChar = ch;}@Overridepublic int getColumns() { // 字符数为字符串字符数加上两侧边框字符数return 1 + display.getColumns() + 1;}@Overridepublic int getRows() { // 行数即被装饰物的行数return display.getRows();}@Overridepublic String getRowText(int row) { // 指定的那一行的字符串为被装饰物的字符串加上两侧的边框的字符return borderChar + display.getRowText(row) + borderChar;}}
public class UpDownBorder extends Border {private char borderChar;// 表示装饰边框的字符public UpDownBorder(Display display, char ch) { // 通过构造函数执行Display和装饰边框字符super(display);borderChar = ch;}@Overridepublic int getColumns() {return display.getColumns();}@Overridepublic int getRows() {return 1 + display.getRows() + 1;}@Overridepublic String getRowText(int row) { // 指定的那一行的字符串if (row == 0) { // 下边框return makeLine(display.getColumns());} else if (row == display.getRows() + 1) { // 上边框return makeLine(display.getColumns());} else { // 其他边框return display.getRowText(row - 1);}}private String makeLine(int count) { // 生成一个重复count次字符ch的字符串StringBuffer buf = new StringBuffer();for (int i = 0; i < count; i++) {buf.append(borderChar);}return buf.toString();}
}
  • Main
public class Main {public static void main(String[] args) {Display b1 = new StringDisplay("Hello, world.");Display b2 = new UpDownBorder(b1, '-');Display b3 = new SideBorder(b2, '*');b1.show();b2.show();b3.show();Display b4 = new FullBorder(new UpDownBorder(new SideBorder(new UpDownBorder(new SideBorder(new StringDisplay("Hello, world."), '*'), '='), '|'),'/'));b4.show();}}

注:博客中的图片来自网上。

【笔记整理】图解设计模式 | 第12章 Decorator模式(装饰边框与被装饰物的一致性)相关推荐

  1. Decorator模式------装饰边框与被装饰物的一致性

    1. >>不断地为对象装饰的设计模式称为Decorator 模式. 2. 示例程序 >>功能:给文字添加装饰边框.这里所谓的装饰边框是指用" - " &qu ...

  2. 装饰边框 与 被装饰物 一致的 Decorator模式

    文章目录 Decorator模式 应用场景 本质 优点 缺点 角色 Decorator模式的类图 示例程序 示例程序的类图 示例代码 拓展思路 相关设计模式 满足的原则 Decorator模式 应用场 ...

  3. 【笔记整理】图解设计模式 | 第16章 Mediator模式(只有一个仲裁者)

    [笔记整理]图解设计模式 | 导航 定义 组员向仲裁者报告,仲裁者向组员下达指示. 当发生麻烦事情的时候,通知仲裁者:当发生涉及全体组员的事情时,也通知仲裁者. 当仲裁者下达指示时,组员会立即执行.团 ...

  4. 设计模式(十二)-装饰器模式(Decorator Pattern)——装饰边框与被饰物的一致性

    装饰器模式(Decorator Pattern)能不断的为对象添加装饰. Display.java package com.test.dp.Decorator.Sample;//抽象类,用于显示字符串 ...

  5. 第 12 章 组合模式

    第 12 章 组合模式 1.学校院系展示需求 看一个学校院系展示需求 编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系. 如图: 2. ...

  6. 【设计模式】第二章 代理模式

    第二章 代理模式 文章目录 第二章 代理模式 一.简介 一.静态代理 二.动态代理 1.JDK 代理 2.CGLib 代理 三.总结 一.简介 你可能会对这个设计模式感到陌生,但是你对 Spring ...

  7. 设计模式——(12)组合模式

    第十二章 组合模式 1.1 引言 餐厅都有自己的一份菜单,而菜单由菜单项组成,每个菜单项描述菜名.菜价和描述等信息. 而在一份菜单中,可能包含子菜单,例如:餐厅菜单除了包含菜名,还包含一份甜品子菜单. ...

  8. 23种设计模式(第二章创建者模式5种)

    第二章创建者模式 单例模式 单例模式有 3 个特点: 单例类只有一个实例对象: 该单例对象必须由单例类自行创建: 单例类对外提供一个访问该单例的全局访问点. 单例模式的实现 单例设计模式分类两种: ​ ...

  9. 设计模式学习每天一个——Decorator模式

    参考 http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html 一.装饰模式: 顾名思义,就是对物品进行装饰,既然是装饰 ...

最新文章

  1. LeetCode Shortest Unsorted Continuous Subarray
  2. leetcode算法题--组合总和 Ⅳ★
  3. Backtrader多周期回测
  4. 多个DataTable的合并成一个新表
  5. 【kafka】kafka RecordAccumulator封装消息流程
  6. centos yum install 默认目录_Centos7如何更换yum仓库
  7. 开课吧:C++开发需要知晓的知识有哪些?
  8. linux虚拟机上lvs-nat的实现
  9. win10下, ColorPix取色器错位 指针偏移问题 解决方法
  10. 软件系统分析设计过程方法精要
  11. 基于HSLcommunication的SiemensTools 西门子PLC 调试工具
  12. SOTIF-雨雪雾行驶场景下交通参与者视觉检测及识别
  13. gmtime() php,C语言gmtime()函数:把clock中的时间转换为格林尼治标准时间
  14. 雷观(十八):我的世界观
  15. ORACLE安装入门篇OEL5.4安装ORACLE11g
  16. c语言tap位置什么意思,CTAP是什么意思
  17. 自问自答学ArrayList,看这篇就够了,详解问答
  18. 移动端border-radius绘制圆点不圆
  19. 怎么查看服务器的性能,查看服务器进程性能查看
  20. 【solr】solr介绍

热门文章

  1. 字库侵权计算机软件,计算机字库的著作权保护与侵权判定.pdf
  2. 《机械制造业智能工厂规划设计》——3.2 机械制造业智能工厂参考模型
  3. 设计模式----代理模式
  4. Word 2007教程:使用多级编号列表
  5. 常用的渗透测试工具总结
  6. 如何在自己网站加入百度手写输入法?
  7. 软件设计模式之(二)装饰者模式
  8. Minitab直方图技巧
  9. 从优站精选上学习Bootstrap案例总结(一)
  10. 【技术贴】超级缓存supercache3设置教程||super chache 3重启开机黑屏的解决办