Java设计模式 —— 装饰模式
12 装饰模式
12.1 装饰模式概述
Decorator Pattern: 动态地给一个对象增加一些额外的职责。提供一种比使用子类更加灵活的方案来扩展功能。
装饰模式是一种用于替代继承的技术,通过一种无须定义子类的方式给对象动态增加职责,使用对象之间的关联关系替代类之间继承关系。
装饰模式结构图如下所示:

12.2 装饰模式实现
12.2.1 抽象构件类
它是具体构件类和抽象装饰类的共同父类,它的引入使得客户端可以以一致的方式处理未装饰的对象和已装饰的对象,实现客户端的透明操作。
public abstract class Component {
public abstract void operation();
}
12.2.2 具体构件类
实现抽象构件中声明的方法,装饰类可以给它增加额外的方法。
public class ConcreteComponent extends Component {
public void operation() {
// 业务代码
}
}
12.2.3 抽象装饰类
用于给具体构件类增加职责,但是具体增加的职责在其子类中实现。
public class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
// 调用原有业务方法
component.operation();
}
}
12.2.4 具体装饰类
负责向具体构件中添加新的职责。
public class ConcreteDecorator extends Decorator {
public concreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();
// 新增的职责
addMethod();
}
public void addMethod() {
// 新增职责逻辑
}
}
12.2.5 客户端调用
public class Client {
public static void main(String[] args) {
Component component, decorator;
component = new ConcreteComponent();
decorator = new ConcreteDecorator(component);
// 一致的方式处理未装饰的对象和已装饰的对象
componet.operation();
decorator.operation();
}
}
12.3 透明装饰模式与半透明装饰模式
12.3.1 透明装饰模式
上述装饰模式的实现即为透明装饰模式,要求客户端完全针对抽象编程。装饰模式的透明性要求客户端程序将对象声明为抽象构件类型,可以一致的处理装饰对象和未装饰对象。
但是在某些情况下,有些新增行为需要单独被调用,此时如果使用透明装饰模式,则无法一致的处理装饰前的对象和装饰后的对象(装饰后的对象需要强制类型转换调用新增行为)。
12.3.2 半透明装饰模式
为了能够调用到新增的方法,不得不用具体装饰类型来定义装饰之后的对象,而具体构件对象可以使用抽象构件声明,这种装饰模式则称为半透明。
public class Client {
Component component;
component = new ConcreteComponent();
component.operation();
ConcreteDecorator decorator = new ConcreteDecorator(component);
decorator.operation();
decorator.addMethod();
}
半透明模式可以给系统带来更多的灵活性,使用起来也非常方便;但是其缺点是客户端需要区别的对象装饰对象和未装饰对象。
12.4 装饰模式优/缺点
使用场景:Java I/O 输入流和输出流
装饰模式的优点主要如下:
- 对于扩展一个类的功能,装饰模式比继承更加灵活
- 可以对一个对象进行多次装饰,通过使用不同的装饰类得到功能更强大的对象
- 具体构件类和具体装饰类可以独立变化,用户根据需要增加新的构件类和装饰类,无须修改原有代码,符合开闭原则
装饰模式的缺点主要如下:
- 装饰模式提供了一种比继承更灵活的方式,同时也比继承更加易于出错,排错也更加困难,对于多次装饰的对象
Java设计模式 —— 装饰模式的更多相关文章
- Java设计模式---装饰模式
装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的结构 装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任.换言之,客户 ...
- Java设计模式-装饰模式(Decorator)
顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...
- Java设计模式—装饰模式
装饰模式是一种比较常见的模式. 定义为:动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更加灵活. 装饰模式的通用类图如下: 装饰模式的构成: 1) 抽象构件(Component ...
- Java设计模式——装饰模式
转载自:http://blog.csdn.net/xu__cg/article/details/53024490 抽象构件 public interface CarInterface { void m ...
- Java设计模式学习记录-装饰模式
前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...
- Java设计模式(7)装饰模式(Decorator模式)
Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...
- Java设计模式(三) 抽象工厂模式
原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...
- Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
- Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...
- Java设计模式(一) 简单工厂模式不简单
摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...
随机推荐
- JavaScript之jQuery要点记录
一 属性和属性节点 1.什么是属性? 对象身上保存的变量就是属性 2.如何操作属性? 对象.属性名称 = 值; 对象.属性名称; 对象["属性名称"] = 值; 对象[" ...
- mongodb定时备份
1. https://www.jianshu.com/p/a9352e28e2d6 (未测试) 通过centos 脚步来执行备份操作,使用crontab实现定时功能,并删除指定天数前的备份 具体操 ...
- Tcp网络模型
要摸清网络,那么第一步肯定是要清楚网络协议的分层结构,用上帝视角来看网络. 对于同一台设备上的进程间通信,有很多种方式,比如有管道.消息队列.共享内存.信号等方式,而对于不同设备上的进程间通信,就需要 ...
- modbus通讯协议详解
1.Modbus 协议简介 Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议.通过此协议,控制器相互之间.或控制器经由网络(如以太网)可以和其它设备之间进行通信.Modbus协议使用 ...
- SpringBoot整合RocketMQ案例实战
一.概念 rocketMQ是一款典型的分布式架构下的中间件产品,使用异步通信方式和发布订阅的消息传输模型,具备异步通信的优势,系统拓扑简单,上下游耦合较弱,主要应用于异步解耦,流量削峰填谷等场景 二. ...
- GO语言学习笔记-并发篇 Study for Go ! Chapter seven - Concurrency
持续更新 Go 语言学习进度中 ...... GO语言学习笔记-类型篇 Study for Go! Chapter one - Type - slowlydance2me - 博客园 (cnblogs ...
- day01-2-依赖管理和自动配置
依赖管理和自动配置 1.依赖管理 1.1什么是依赖管理 spring-boot-starter-parent 中还有父项目,声明了开发中常用的依赖的版本号 并且进行自动版本仲裁,即如果程序员没有指定某 ...
- Python学习笔记--循环的知识以及应用
while循环 代码: 结果: 案例:求1-100的和 实现: 案例:while循环猜数字 实现: while循环的嵌套使用 案例:打印九九乘法表 (注意:要是想要输出不换行,代码可以这样写:prin ...
- (新手向)在Linux中使用VScode编写 "Hello,world"程序,并编写测试-Ubuntu20.4
本文意在帮助 Go 语言初学者在 Linux环境下编写自己的第一个Golang程序 难点主要在 VScode 中 Go 插件的下载 与 go.mod 以及编译运行和 第一个Go测试程序的使用 前提准备 ...
- 53.cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
1.cin 用法1:最基本,也是最常用的用法,输入一个数字: #pragma warning(disable:4996) #define _CRT_SECURE_NO_WARNINGS 1 #incl ...