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

  • 优点:在某些时候装饰模式比继承(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. STM32入门系列-GPIO概念介绍

    GPIO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来控制其输入和输出.STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯 ...

  2. AQS源码深入分析之条件队列-你知道Java中的阻塞队列是如何实现的吗?

    本文基于JDK-8u261源码分析 1 简介 因为CLH队列中的线程,什么线程获取到锁,什么线程进入队列排队,什么线程释放锁,这些都是不受我们控制的.所以条件队列的出现为我们提供了主动式地.只有满足指 ...

  3. Dorado download注意事项

    uploader/uploader-SNAPSHOT uploader/uploader-RELEASE .....使用需要注意!

  4. C# 集合类(四)

    C# 集合类自己经常用到: 数组(Array).动态数组(ArrayList).列表(List).哈希表(Hashtable).字典(Dictionary),对于经常使用的这些数据结构,做一个总结,便 ...

  5. python实现对于告警规则的判断思路

    场景 监控一个后台服务各个url的响应时间,需要在mysql数据库的一张表中设计一个字段需要包含且不仅限于以下一种规则(1. 大于 2. 小于 3. 大于等于 4. 小于等于),表结构大概是这样的 每 ...

  6. JavaScript变量声明与变量声明提前

    JavaScript变量声明 JavaScript中存储数据的容器称为变量.用关键字和标识符创建新变量的语句,称为变量声明.可以通过关键字var进行变量声明,在ES6中增加了let.const关键字声 ...

  7. debian修改crontab默认编辑器为vim

    debian终端下默认编辑器为nano,比如crontab -e就会打开nano,这个编辑器用起来很不习惯,想修改为vim,当然,你的debian系统必须先安装vim.如果已经安装vim,请输入如下命 ...

  8. 协程实现爬虫的例子主要优势在于充分利用IO时间去请求其他的url

    # 分别使用urlopen和requests两个模块进行演示 # import requests # 需要安装的 # from urllib.request import urlopen # # ur ...

  9. Cisco思科模拟器路由器各个端口IP地址的配置及路由协议RIP的配置 入门详解 - 精简归纳

    Cisco思科模拟器路由器各个端口IP地址的配置及路由协议RIP的配置 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 11 / 21 转载请注明出处!️ 附: 交流方式: ️ ️ ️ Q ...

  10. [web安全原理]PHP命令执行漏洞基础

    前言 PHP命令执行漏洞 应用程序的某些功能功能需要调用可以执行系统命令的函数,如果这些函数或者函数的参数被用户控制,就有可能通过命令连接符将恶意命令拼接到正常的函数中,从而随意执行系统命令,这就是命 ...