zoukankan      html  css  js  c++  java
  • 设计模式——装饰者模式

    一、定义与简单实现

    1、定义

    •  动态地将责任附加到对象上去,提供了比继承更有弹性的替代方案。

    装饰者模式是类继承的另外一种选择。类继承在编译时候增加行为,而装饰者模式是在运行时增加行为。

    通过使用修饰模式,可以在运行时扩充一个类的功能。原理是:创建一个装饰类,组合目标类,然后动态的增强目标对象的方法,

    注意:装饰类必须目标对象有相同的接口

    2、UML类图

     装饰者模式是个常用的模式。重点是需要有相同的接口,然后要利用组合,不要利用继承。

    我理解的UML类图

     

     官方UML类图给装饰者再加一层抽象类:这里抽象类作用是复用代码,没有这个需求时,可以不用加,后面框架中的实现,就没有加

    动态地将责任附加到对象上去,若要扩展功能,装饰着提供了比继承更有弹性的替代方案用到的设计模式原则:

    • 多用组合,少用继承
    • 针对接口编程
    • 对扩展开发,对修改关闭

    3、简单实现

    前面:mybatis——缓存:redis实现分布式二级缓存

    public interface Component {
        void methodA();
    }
    
    public class ConcreteComponent implements Component {
        @Override
        public void methodA() {
            System.out.println("想加特技");
        }
    }
    
    public class DecoratorComponent implements Component {
    
        private Component component;
    
        public DecoratorComponent(Component component){
            this.component = component;
        }
    
        @Override
        public void methodA() {
            component.methodA();
            System.out.println("特技得加钱");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Component concrete = new ConcreteComponent();
            Component decorator = new DecoratorComponent(concrete);
            decorator.methodA();
        }
    }

    二、框架中的装饰者模式

    1、JDK中输入输出流

    FilterInputStream的类其实是左边InputStream类的一个装饰者类。

     

    2、Mybatis二级缓存

    mybatis源码中org.apache.ibatis.cache.decorators包下的类全是装饰类,都是对二级缓存类PerpetualCache.class功能的增强。例如

    FifoCache:增强缓存置换功能,设置缓存大小,当缓存满后,先进先出(FIFO)算法置换(利用队列实现)

    LruCache:增强缓存置换功能,设置缓存大小,当缓存满后,最久未使用(LRU)算法置换(利用LinkedHashMap实现)

     

     其实这里的FifoCache、LruCache中可以加一层抽象类,因为有共同的方法getId()等

    下面是二级缓存创建,Configuration.caches

    /* org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache */
      public Cache useNewCache(Class<? extends Cache> typeClass,
          Class<? extends Cache> evictionClass,
          Long flushInterval,
          Integer size,
          boolean readWrite,
          boolean blocking,
          Properties props) {
          //建造器模式创建cache
        Cache cache = new CacheBuilder(currentNamespace)
            .implementation(valueOrDefault(typeClass, PerpetualCache.class))
            .addDecorator(valueOrDefault(evictionClass, LruCache.class))
            .clearInterval(flushInterval)
            .size(size)
            .readWrite(readWrite)
            .blocking(blocking)
            .properties(props)
            .build();
        configuration.addCache(cache);
        currentCache = cache;
        return cache;
      }
    
      public Cache build() {
        //默认implementation = PerpetualCache.class
        //decorators.add(LruCache.class)
        setDefaultImplementations();
        //利用反射创建一个PerpetualCache实例
        //类似 Cache cache = new PerpeualCache(id);
        Cache cache = newBaseCacheInstance(implementation, id);
        setCacheProperties(cache);
        // issue #352, do not apply decorators to custom caches
        if (PerpetualCache.class.equals(cache.getClass())) {
          for (Class<? extends Cache> decorator : decorators) {
            //装饰者模式功能增强,注意这里是个循环,可多次增强
            //默认LruCache.class
            //类似cache = new LruCache(cache);
            cache = newCacheDecoratorInstance(decorator, cache);
            setCacheProperties(cache);
          }
          cache = setStandardDecorators(cache);
        } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
          cache = new LoggingCache(cache);
        }
        return cache;
      }

    补充:装饰者模式中装饰者对象必须依赖原对象,可用工厂模式或者建造者模式封装整个创建过程。

  • 相关阅读:
    request转换为java bean
    idea中快捷键
    idea中Terminal显示中文乱码
    idea解决tomcat控制台中文乱码问题
    需要看的url
    常用网站
    反射
    5、运算符
    4、变量
    2、Hello Word讲解
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12620505.html
Copyright © 2011-2022 走看看