【笔记整理】图解设计模式 | 第12章 Decorator模式(装饰边框与被装饰物的一致性)
【笔记整理】图解设计模式 | 导航
定义
- 不断地为对象添加装饰的设计模式被称为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模式(装饰边框与被装饰物的一致性)相关推荐
- Decorator模式------装饰边框与被装饰物的一致性
1. >>不断地为对象装饰的设计模式称为Decorator 模式. 2. 示例程序 >>功能:给文字添加装饰边框.这里所谓的装饰边框是指用" - " &qu ...
- 装饰边框 与 被装饰物 一致的 Decorator模式
文章目录 Decorator模式 应用场景 本质 优点 缺点 角色 Decorator模式的类图 示例程序 示例程序的类图 示例代码 拓展思路 相关设计模式 满足的原则 Decorator模式 应用场 ...
- 【笔记整理】图解设计模式 | 第16章 Mediator模式(只有一个仲裁者)
[笔记整理]图解设计模式 | 导航 定义 组员向仲裁者报告,仲裁者向组员下达指示. 当发生麻烦事情的时候,通知仲裁者:当发生涉及全体组员的事情时,也通知仲裁者. 当仲裁者下达指示时,组员会立即执行.团 ...
- 设计模式(十二)-装饰器模式(Decorator Pattern)——装饰边框与被饰物的一致性
装饰器模式(Decorator Pattern)能不断的为对象添加装饰. Display.java package com.test.dp.Decorator.Sample;//抽象类,用于显示字符串 ...
- 第 12 章 组合模式
第 12 章 组合模式 1.学校院系展示需求 看一个学校院系展示需求 编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系. 如图: 2. ...
- 【设计模式】第二章 代理模式
第二章 代理模式 文章目录 第二章 代理模式 一.简介 一.静态代理 二.动态代理 1.JDK 代理 2.CGLib 代理 三.总结 一.简介 你可能会对这个设计模式感到陌生,但是你对 Spring ...
- 设计模式——(12)组合模式
第十二章 组合模式 1.1 引言 餐厅都有自己的一份菜单,而菜单由菜单项组成,每个菜单项描述菜名.菜价和描述等信息. 而在一份菜单中,可能包含子菜单,例如:餐厅菜单除了包含菜名,还包含一份甜品子菜单. ...
- 23种设计模式(第二章创建者模式5种)
第二章创建者模式 单例模式 单例模式有 3 个特点: 单例类只有一个实例对象: 该单例对象必须由单例类自行创建: 单例类对外提供一个访问该单例的全局访问点. 单例模式的实现 单例设计模式分类两种: ...
- 设计模式学习每天一个——Decorator模式
参考 http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html 一.装饰模式: 顾名思义,就是对物品进行装饰,既然是装饰 ...
最新文章
- LeetCode Shortest Unsorted Continuous Subarray
- leetcode算法题--组合总和 Ⅳ★
- Backtrader多周期回测
- 多个DataTable的合并成一个新表
- 【kafka】kafka RecordAccumulator封装消息流程
- centos yum install 默认目录_Centos7如何更换yum仓库
- 开课吧:C++开发需要知晓的知识有哪些?
- linux虚拟机上lvs-nat的实现
- win10下, ColorPix取色器错位 指针偏移问题 解决方法
- 软件系统分析设计过程方法精要
- 基于HSLcommunication的SiemensTools 西门子PLC 调试工具
- SOTIF-雨雪雾行驶场景下交通参与者视觉检测及识别
- gmtime() php,C语言gmtime()函数:把clock中的时间转换为格林尼治标准时间
- 雷观(十八):我的世界观
- ORACLE安装入门篇OEL5.4安装ORACLE11g
- c语言tap位置什么意思,CTAP是什么意思
- 自问自答学ArrayList,看这篇就够了,详解问答
- 移动端border-radius绘制圆点不圆
- 怎么查看服务器的性能,查看服务器进程性能查看
- 【solr】solr介绍