装饰模式(Decorator Pattern)

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

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

装饰模式类图

装饰模式的组成

(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

应用场景

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

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

责任链模式的实现原理

  • 每个被调用者都持有下一个被调用者的引用,客户端只需要发起第一个调用者即可完成所有的操作。
  • 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;
    }
}

相关文章链接:
<<<23中常用设计模式总览
<<<代理模式(Proxy Pattern)
<<<装饰模式(Decorator Pattern)
<<<观察者模式(Observer Pattern)
<<<单例模式(Singleton Pattern)
<<<责任链模式(Chain of Responsibility Pattern)
<<<策略模式(Strategy Pattern)
<<<模板方法模式(Template Pattern)
<<<外观/门面模式(Facade Pattern)
<<<建造者模式(Builder Pattern)
<<<适配器模式(Adapter Pattern)
<<<原型模式(Prototype Pattern)
<<<工厂相关模式(Factory Pattern)

原文地址:https://www.cnblogs.com/jarye/p/13962049.html