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中就可以了!!!