【设计模式】装饰者模式(DecoratorMode0
From: https://liudongdong1.github.io/
装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类. 装饰模式的核心在于抽象装饰类的设计。
- 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
- Component(抽象构件):它是
具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。 - ConcreteComponent(具体构件):它是抽象构件类的子类,用于
定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。 - Decorator(抽象装饰类):它也是
抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。 - ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。
每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
1. Demo1

煎饼 加一个鸡蛋 加一个鸡蛋 加一根香肠, 销售价格: 12
public abstract class ABattercake {
protected abstract String getDesc();
protected abstract int cost();
}
public class Battercake extends ABattercake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
- 抽象装饰类,需要注意的是,抽象装饰类通过成员属性的方式将 煎饼抽象类组合进来,同时也继承了煎饼抽象类
public abstract class AbstractDecorator extends ABattercake {
private ABattercake aBattercake;
public AbstractDecorator(ABattercake aBattercake) {
this.aBattercake = aBattercake;
}
protected abstract void doSomething();
@Override
protected String getDesc() {
return this.aBattercake.getDesc();
}
@Override
protected int cost() {
return this.aBattercake.cost();
}
}
public class EggDecorator extends AbstractDecorator {
public EggDecorator(ABattercake aBattercake) {
super(aBattercake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + " 加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost() + 1;
}
public void egg() {
System.out.println("增加了一个鸡蛋");
}
}
2. Demo2
下面需求开始:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:
具体需求:
1、武器(攻击力20) 、戒指(攻击力5)、护腕(攻击力5)、鞋子(攻击力5)
2、蓝宝石(攻击力5/颗)、黄宝石(攻击力10/颗)、红宝石(攻击力15/颗)
3、每个装备可以随意镶嵌3颗
package com.zhy.pattern.decorator;
/**
* 装备的接口
*
* @author zhy
*
*/
public interface IEquip
{
/**
* 计算攻击力
*
* @return
*/
public int caculateAttack();
/**
* 装备的描述
*
* @return
*/
public String description();
}
//Equip 实例
package com.zhy.pattern.decorator;
/**
* 武器
* 攻击力20
* @author zhy
*
*/
public class ArmEquip implements IEquip
{
@Override
public int caculateAttack()
{
return 20;
}
@Override
public String description()
{
return "屠龙刀";
}
}
//宝石超类
package com.zhy.pattern.decorator;
/**
* 装饰品的接口
* @author zhy
*
*/
public interface IEquipDecorator extends IEquip
{
}
package com.zhy.pattern.decorator;
/**
* 蓝宝石装饰品
* 每颗攻击力+5
* @author zhy
*
*/
public class BlueGemDecorator implements IEquipDecorator
{
/**
* 每个装饰品维护一个装备
*/
private IEquip equip;
public BlueGemDecorator(IEquip equip)
{
this.equip = equip;
}
@Override
public int caculateAttack()
{
return 5 + equip.caculateAttack();
}
@Override
public String description()
{
return equip.description() + "+ 蓝宝石";
}
}
package com.zhy.pattern.decorator;
public class Test
{
public static void main(String[] args)
{
// 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
System.out.println(" 一个镶嵌2颗红宝石,1颗蓝宝石的靴子");
IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");
// 一个镶嵌1颗红宝石,1颗蓝宝石的武器
System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器");
equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");
}
}
3. Java I/O中的装饰者模式


如果要实现一个自己的包装流,根据上面的类图,需要继承抽象装饰类 FilterInputStream,譬如来实现这样一个操作的装饰者类:将输入流中的所有小写字母变成大写字母
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class UpperCaseInputStream extends FilterInputStream {
protected UpperCaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int result = super.read(b, off, len);
for (int i = off; i < off + result; i++) {
b[i] = (byte) Character.toUpperCase((char) b[i]);
}
return result;
}
public static void main(String[] args) throws IOException {
int c;
InputStream in = new UpperCaseInputStream(new FileInputStream("D:\\hello.txt"));
try {
while ((c = in.read()) >= 0) {
System.out.print((char) c);
}
} finally {
in.close();
}
}
}
4. spring cache 中的装饰者模式

public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache;
public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, "Target Cache must not be null");
this.targetCache = targetCache;
}
public <T> T get(Object key, Class<T> type) {
return this.targetCache.get(key, type);
}
public void put(final Object key, final Object value) {
// 判断是否开启了事务
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 将操作注册到 afterCommit 阶段
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
}
});
} else {
this.targetCache.put(key, value);
}
}
// ...省略...
}
5. spring session 中的装饰者模式

public class ServletRequestWrapper implements ServletRequest { private ServletRequest request; public ServletRequestWrapper(ServletRequest request) { if (request == null) { throw new IllegalArgumentException("Request cannot be null"); } this.request = request; } @Override public Object getAttribute(String name) { return this.request.getAttribute(name); } //...省略...}
6. Mybatis 缓存中的装饰者模式

Resource
- https://juejin.cn/post/6844903681322647566
- Java日志框架:slf4j作用及其实现原理
- HankingHu:由装饰者模式来深入理解Java I/O整体框架
- HryReal:Java的io类的使用场景
- Todo: 进一步补充
【设计模式】装饰者模式(DecoratorMode0的更多相关文章
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- JAVA设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- 从源码角度理解Java设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
- 【设计模式】Java设计模式 - 装饰者模式
Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...
- [Head First设计模式]山西面馆中的设计模式——装饰者模式
引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里也就依葫芦画瓢,换汤不换药的用装饰者模式来模拟一碗鸡蛋面是怎么出来的吧.吃 ...
- JAVA 设计模式 装饰者模式
用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
- javascript设计模式——装饰者模式
前面的话 在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么可以使用装饰者模式.装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.本文将 ...
- 设计模式-装饰者模式(Decorator Pattern)
本文由@呆代待殆原创,转载请注明出处. 此设计模式遵循的设计原则之一:类应该支持扩展,而拒绝修改(Open-Closed Principle) 装饰者模式简述 装饰者模式通过组合的方式扩展对象的特性, ...
- C#设计模式--装饰器模式
0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...
随机推荐
- DHCP工作原理
DHCP:Dynamic Host Configurtion Protocol DHCP的工作原理(UDP) 1.客户端:首先会发送给一个dhcp discovery(广播)报文,报文中的2层和3层都 ...
- Python单元测试框架unittest之单用例管理(一)
一.概述 本文介绍python的单元测试框架unittest,unittest原名为PyUnit,是由java的JUnit衍生而来,这是Python自带的标准模块unittest.unittest是基 ...
- 让5G技术“智慧”生活
1.通讯技术的发展历程 2.5G技术的指标和具体概述 3. 5G的三个关键技术及概述 4.5G的应用场景及业务及安全挑战 如果你认为5G带来的只是下载视频 ...
- SpringBoot配置Https
HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认 ...
- SLAM的数学基础(1):什么是方差,有什么意义?
小红班上有两组同学的数学考试分数为: 第一组:小红:100分,小明:60分,小宇:20分 第二组:小蓝:70分,小华:60分,小杰:50分 那么很容易算出,第一组的平均分是60分,第二组的平均分也是6 ...
- Map集合笔记
一.Map集合的特点 Map集合是一个双列集合 Map中的元素,key和value的数据类型可以相同,也可以不同. Map中的元素,key是允许重复的,value是可以重复的 Map中的元素,key和 ...
- python内置函数dir()
描述 dir() 函数不带参数时,返回当前范围内的变量.方法和定义的类型列表:带参数时,返回参数的属性.方法列表.如果参数包含方法__dir__(),该方法将被调用.如果参数不包含__dir__(), ...
- 手写一个超简单的Vue
基本结构 这里我根据自己的理解模仿了Vue的单文件写法,通过给Vue.createApp传入参数再挂载元素来实现页面与数据的互动. 其中理解不免有错,希望大佬轻喷. 收集数据 这里将Vue.creat ...
- 为什么每次下载后必须关闭掉IO流(十五)
读一个文件,忘记关闭了流,你在操作系统里对这个文件的写,删除等操作就会报错,告诉你这个文件被某个进程占用,这是为什么呢? java是从c++设计来的,但是无论是C语言还是C++,都需要手动释放内存,j ...
- PostgreSQL-WITH AS短语
WITH提供了一种方式来书写在一个大型查询中使用的辅助语句.这些语句通常被称为公共表表达式或CTE,它们可以被看成是定义只在一个查询中存在的临时表.在WITH子句中的每一个辅助语句可以是一个SELEC ...