使用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))

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

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

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

上一篇:C++ static全局变量与全局变量的区别/static全局函数与全局函数的区别


下一篇:jQuery知识大杂汇