代理模式:动态地给一个对象添加一些额外的职责,它比生成子类方式更为灵活。

  • 优点:在某些时候装饰模式比继承(inheritance)要更加灵活

装饰模式的组成

(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类

(2)具体组件:将要被附加功能的类,实现抽象构件角色接口

(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口

(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

应用场景

  • Spring Session
  • Mybatis的一级二级缓存
  • I/O 流(基于字符流[InputStream/OutputStream] 和 字节流[Reader/Writer]作为基类,eg:new FileInputStream(new File()),以下为Reader的类图)

装饰模式与责任链模式区别

责任链模式的实现原理

  • 每个被调用者都持有下一个被调用者的引用,客户端只需要发起第一个调用者即可完成所有的操作。
  • new A()-->new B()-->new C()====>A-->B-->C

装饰模式的实现原理

  • 持有被装饰的对象,需具备被装饰者的行为,对其行为进行补充增强
  • new A(new B(new C()))====>C-->B-->A

自定义注解实现多级缓存

a.注解定义

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExtJaryeCache {
}

b.注解使用

@RequestMapping("/getUser")
@ExtJaryeCache
public UserEntity getUser(Integer userId) {
return userMapper.findByUser(userId);
}

c.注解拦截

@Aspect
@Component
@Slf4j
public class ExtAsyncAop {
@Autowired
private JaryeCacheUtils jaryeCache; /**
* 使用Aop拦截我们的方法上是否使用缓存注解
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around(value = "@annotation(com.jarye.aop.ExtJaryeCache)")
public Object doAround(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
// 获取目标方法
Method targetMethod = methodSignature.getMethod();
// // 拼接缓存的key
String key = targetMethod.getName() + Arrays.toString(targetMethod.getParameterTypes()) +
Arrays.toString(joinPoint.getArgs()); return jaryeCache.getCacheEntity(key,Object.class,joinPoint);
}
}

d.装饰模式核心方法

public <T> T getCacheEntity(String key,Class<T> t, ProceedingJoinPoint joinPoint) {
// 先查询二级缓存
T redisUser = redisUtils.getEntity(key, t);
if (redisUser != null) {
return (T) redisUser;
}
// 如果一级缓存存在数据
T jvmUser = super.getCacheEntity(key,t,joinPoint);
if (jvmUser == null) {
return null;
}
// 将该缓存数据放入到二级缓存中
redisUtils.putEntity(key, jvmUser);
return (T) jvmUser;
}
public <T> T getCacheEntity(String key, Class<T> t,ProceedingJoinPoint joinPoint) {
// 先查询我们的一级缓存(Jvm内置)
UserEntity jvmUser = JvmMapCacheUtils.getEntity(key, UserEntity.class);
if (jvmUser != null) {
return (T) jvmUser;
}
// 查询我们的db 通过aop直接获取到我们的目标对象方法
try {
Object resultDb = joinPoint.proceed();
// 数据库DB有的情况 将该内容缓存到当前Jvm中
JvmMapCacheUtils.putEntity(key, resultDb);
return (T) resultDb;
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}

装饰模式(Decorator Pattern)的更多相关文章

  1. 二十四种设计模式:装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern) 介绍动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活.示例有一个Message实体类,某个对象对它的操作有Insert()和 ...

  2. 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)

    原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...

  3. 设计模式-装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活

  4. 设计模式-09装饰模式(Decorator Pattern)

    1.模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制:使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是 ...

  5. 设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  6. 装饰模式(Decorator pattern)

    装饰模式(Decorator pattern): 又名包装模式(Wrapper pattern), 它以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式以对客户透明的方式动态的给 ...

  7. 设计模式系列之装饰模式(Decorator Pattern)

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原 ...

  8. 装饰模式Decorator Pattern

    1.主要优点 装饰模式的主要优点如下: (1) 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加. (3) 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类 ...

  9. 设计模式——装饰模式(Decorator Pattern)

    装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. UML图: 模型类: Component类: package com.cnblog.clarck; /** ...

  10. 使用C# (.NET Core) 实现装饰模式 (Decorator Pattern) 并介绍 .NET/Core的Stream

    该文章综合了几本书的内容. 某咖啡店项目的解决方案 某咖啡店供应咖啡, 客户买咖啡的时候可以添加若干调味料, 最后要求算出总价钱. Beverage是所有咖啡饮料的抽象类, 里面的cost方法是抽象的 ...

随机推荐

  1. Java Arrays 和 List的相互转化

    最近在 leetcode 刷题的时候遇到过好几次这样的情况:需要返回的数据类型是数组(Arrays),但是求解的时候并不知道数组的长度,这时候就需要先用 List 进行临时存储,最后再转化为 Arra ...

  2. 4-20mA转RS485模拟量采集模块是怎么工作的?

    4-20mA信号是工业上常用的模拟信号,用来表示温度,距离,速度,角度等参数. 如果需要用PLC或者工控机来采集,通常要转换成数字信号.这时可以采购远向电子生产的模拟量采集模块. 常用的模拟量采集模块 ...

  3. 关于appium

    一.特点 1.appium是开源的移动端自动化测试框架: 2.appium可以测试原生的.混合的.以及移动端的web项目: "移动原生应用"是指那些用iOS或者 Android S ...

  4. Docker学习—Compose

    前言 前面<Docker学习-DockerFile>文中介绍了dockerfile相关的语法,及使用方式:接下来了解docker三剑客之一的 Compose:接下来详细学习. 一.dock ...

  5. JWT基本概念

    json web token 简称 JWT,它并不是一个具体的技术实现,而更像是一种标准. JWT规定了数据传输的结构,一串完整的JWT由三段落组成,每个段落用英文句号连接(.)连接,他们分别是:He ...

  6. Spider_基础总结2_Requests异常

    # 1: BeautifulSoup的基本使用: import requests from bs4 import BeautifulSoup html=requests.get('https://ww ...

  7. Pytorch显存动态分配规律探索

    下面通过实验来探索Pytorch分配显存的方式. 实验 显存到主存 我使用VSCode的jupyter来进行实验,首先只导入pytorch,代码如下: import torch 打开任务管理器查看主存 ...

  8. 链路层输出 -qdisc

    二层发送中,实现qdisc的主要函数是__dev_xmit_skb和net_tx_action,本篇将分析qdisc实现的原理,仅对框架进行分析. 其框架如下图所示 qdisc初始化 pktsched ...

  9. golang 简单工厂模式

    package kit //golang简单工厂模式 //go 语言没有构造函数一说,所以一般会定义NewXXX函数来初始化相关类. NewXXX 函数返回接口时就是简单工厂模式,也就是说Golang ...

  10. Oracle 集合类型

    集合类型 1. 使用条件: a. 单行单列的数据,使用标量变量 .    b. 单行多列数据,使用记录 [ 详细讲解请见: 点击打开链接 ]   c. 单列多行数据,使用集合 *集合:类似于编程语言中 ...