美文网首页RxJavaJava服务器端编程编程语言爱好者
设计模式-装饰模式(Decorator Pattern)

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

作者: 迦叶_金色的人生_荣耀而又辉煌 | 来源:发表于2020-11-11 23:07 被阅读0次

    上一篇 <<<@Async失效之谜
    下一篇 >>>观察者模式(Observer 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)
    <<<观察者模式(Observer Pattern)
    <<<单例模式(Singleton Pattern)
    <<<责任链模式(Chain of Responsibility Pattern)
    <<<策略模式(Strategy Pattern)
    <<<模板方法模式(Template Pattern)
    <<<外观/门面模式(Facade Pattern)
    <<<建造者模式(Builder Pattern)
    <<<适配器模式(Adapter Pattern)
    <<<原型模式(Prototype Pattern)
    <<<工厂相关模式(Factory Pattern)

    相关文章

      网友评论

        本文标题:设计模式-装饰模式(Decorator Pattern)

        本文链接:https://www.haomeiwen.com/subject/qloybktx.html