• 使用Groovy的mixin方法注入,和mixedIn属性实现过滤链


    mixin方法注入不多说,这里只是用这个属性搞一个过滤器链的功能

    假设我现在有个方法,输入一个字符串,然后需求提出需要进行大写转换输出,

    过了一天又要加个前缀,再过了一天,需要把一些字符过滤掉......一直修改代码肯定是最low的,所以可以利用mixedIn属性,

    设计一个过滤链,加需求,只需要新增一个过滤器就行了!

    目标实例:

    class StringWriter extends MyWriter {
        @Override
        void write(String message) {
            println message
        }
    }
    

      主要实现字符串打印

    注入的过滤器,我这里只设计两个:

    转大写:

    class UpperCaseFilter {
        void write(String message){
            def upperCase = message.toUpperCase()
            //将转换后的消息传递给下一个mixin链条
            def clazz = this.getClass()
            //遍历mixin的链表,找到当前mixin的前一个
            /**
             * mixedIn: groovy提供的一个属性,为实例保存有序的mixin注入类链表
             */
            for(mixin in mixedIn.mixinClasses){
                //会按添加顺序从前往后开始遍历,如果实例不是当前实例,那么就继续
                //直到找到当前实例时,执行的clazz是前一个mixin,最后一个mixin的是目标实例
                if(mixin.mixinClass.theClass==metaClass.delegate.theClass) break
                clazz=mixin.mixinClass.theClass  //一直赋值,break时,clazz刚好是当前实例的前一个
            }
            //如果当前实例在mixin中,执行当前实例方法,否则执行目标实例方法
            mixedIn[clazz].write(upperCase)
        }
    }
    

      

    加前缀:

    class PrefixFilter {
    
        void write(String message){
            message="prefix-----:"+message
            def clazz = this.getClass()
            //遍历mixin的链表,找到当前mixin的前一个
            for(mixin in mixedIn.mixinClasses){
                if(mixin.mixinClass.theClass==metaClass.delegate.theClass) break
                clazz=mixin.mixinClass.theClass
            }
            mixedIn[clazz].write(message)
        }
    }
    

      可以把遍历调用这块抽取出来或者注入到object更好,我这里懒就不弄了,主要是熟悉这个设计

    方法测试:

    def sendMessage(MyWriter write){
        write.write("this is groovy")
    }
    //创建添加过滤器的writer实例
    def creeateInstance(MyWriter writer,Object[] filters =[]){
        //将过滤器注入到writer实例的mixin中
        filters.each {filter-> writer.metaClass.mixin filter}
        writer
    }
    //当注入多个同名同参方法时,最后加入mixin中的方法会自动隐藏掉前面的方法
    // 所以默认前面的不会执行,只会执行最后一个
    /**
     * 这里需要按照需求控制顺序,因为过滤器会按照顺序严格执行,比如,是先加前缀还是先转大写
     */
    sendMessage(creeateInstance(new StringWriter(),PrefixFilter,UpperCaseFilter))
    sendMessage(creeateInstance(new StringWriter(),UpperCaseFilter,PrefixFilter))
    

      结果,顺序不同,结果不同:

    加需要的时候,只需要加个filter注入到StringWriter中就可以了!!!

  • 相关阅读:
    玲珑学院-ACM比赛1014
    扩展欧几里得算法
    中国剩余定理(孙子定理)及实现----原理详解
    搞懂树状数组
    HDU3792---Twin Prime Conjecture(树状数组)
    树状数组 模板
    HDU1541--Stars(树状数组)
    HDU4046--Panda(树状数组)
    CCF-201604-1-折点计数
    CCF-201604-2-俄罗斯方块
  • 原文地址:https://www.cnblogs.com/houzheng/p/10741716.html
Copyright © 2020-2023  润新知