Groovy 将所有后续调用委托给另一个对象引用

Groovy 将所有后续调用委托给另一个对象引用,groovy,Groovy,我有一个方法,它需要一个特定的类作为参数 def walkOver(IWalker instance) { def list = [1, 2, 3, 4, 5] list.each { instance.enterItem(it) if (it.isOdd()) { instance.enterOdd(it) instance.exitOdd(it) } else {

我有一个方法,它需要一个特定的类作为参数

def walkOver(IWalker instance) {
    def list = [1, 2, 3, 4, 5]
    list.each {
        instance.enterItem(it)
        if (it.isOdd()) {
            instance.enterOdd(it)
            instance.exitOdd(it)
        } else {
            instance.enterEven(it)
            instance.exitEven(it)
        }
        instance.exitItem(it)
    }
}
基本上,我遍历一个列表,并对其元素执行某些操作

Class
IWalker
看起来像这样

class IWalker {
    void enterItem(item) { }
    void exitItem(item) { }
    void enterOdd(item) { }
    void exitOdd(item) { }
    void enterEven(item) { }
    void exitEven(item) { }
    void enterCommon(item) { }
    void exitCommon(item) { }
}
class CompositeWalker extends IWalker {
    @Lazy def oddWalker = new OddWalker()
    @Lazy def evenWalker = new EvenWalker()

    void enterItem(item) {
        if (item.isOdd()) {
            // delegate all IWalker calls to oddWalker
        }
    }
    void exitItem(item) {
        // return to current object
    }
}
我有两个
IWalker
的原始子类,它们只执行特定的任务

class OddWalker extends IWalker {
    void enterOdd(item) {
        println "Odd: $item"
    }
    void exitOdd(item) {}
    void enterCommon(item) {}
    void exitCommon(item) {}
}

class EvenWalker extends IWalker {
    void enterEven(item) {
        println "Even: $item"
    }
    void exitEven(item) {}
    void enterCommon(item) {}
    void exitCommon(item) {}
}
我还有一个复合walker,它应该将操作委托给相应的
IWalker
实现的实例

class CompositeWalker extends IWalker {
    @Lazy def oddWalker = new OddWalker()
    @Lazy def evenWalker = new EvenWalker()

    def currentRef = this // default

    void enterItem(item) {}
    void exitItem(item) {}

    void enterOdd(item) {
        currentRef = oddWalker
        currentRef.enterOdd(item) 
    }

    void exitOdd(item) {
        currentRef.exitOdd(item)
        currentRef = this
    }

    void enterEven(item) {
        currentRef = evenWalker
        currentRef.enterEven(item)
    }
    void exitEven(item) {
        currentRef.exitEven(item)
        currentRef = this
    }

    void enterCommon(item) {
        if (currentRef == this) {
            // code
        } else {
            currentRef.enterCommon(item)
        }
    }
    void exitCommon(item) {
        if (currentRef == this) {
            // code
        } else {
            currentRef.enterCommon(item)
        }
    }
}
我希望我的
CompositeWalker
walkOver
方法中所有方法的后续调用委托给相应的对象

目前,我存储了对当前对象的引用,并仅调用其方法

理想情况下,我想做这样的事情

class IWalker {
    void enterItem(item) { }
    void exitItem(item) { }
    void enterOdd(item) { }
    void exitOdd(item) { }
    void enterEven(item) { }
    void exitEven(item) { }
    void enterCommon(item) { }
    void exitCommon(item) { }
}
class CompositeWalker extends IWalker {
    @Lazy def oddWalker = new OddWalker()
    @Lazy def evenWalker = new EvenWalker()

    void enterItem(item) {
        if (item.isOdd()) {
            // delegate all IWalker calls to oddWalker
        }
    }
    void exitItem(item) {
        // return to current object
    }
}
在那里,我根本没有在
compositeWalker
内部实现
oddwarker
evenWalker
方法


可以这样做吗?

通过使用@Delegate注释,您可以摆脱常见方法的实现

class CompositeWalker extends IWalker {

    @Lazy IWalker oddWalker = new OddWalker()
    @Lazy IWalker evenWalker = new EvenWalker()

    @Delegate
    IWalker currentRef = this // default

    void enterItem(item) {}
    void exitItem(item) {}

    void enterOdd(item) {
        currentRef = oddWalker
        currentRef.enterOdd(item)
    }

    void exitOdd(item) {
        currentRef.exitEven(item)
        currentRef = this
    }

    void enterEven(item) {
        currentRef = evenWalker
        currentRef.enterEven(item)
    }
    void exitEven(item) {
        currentRef.exitEven(item)
        currentRef = this
    }
}

对我来说,你的代码有些问题。请注意,您正在调用
isOdd()
两次:在
walkOver()
中和在
CompositeWalker
中。所以你基本上做了两次相同的决定。另外,
IWalker
中的偶数/奇数对及其相应的偶数/奇数实现是一条线索,表明您使用策略模式的方式可能存在缺陷

虽然让
复合程序员
委托给合适的
IWalker
,但我认为有更好的方法;根据我对你代码的理解。我提出了一种重构方法,使用工厂来选择合适的walker,让walker做自己的事情,而完全不考虑项目是偶数还是奇数;因为已经做出了选择。下面是:

def walkOver(IWalkerFactory factory) {
    def list = [1, 2, 3, 4, 5]
    list.each {
        def walker = factory.get(it)

        walker.enterItem(it)        
        walker.exitItem(it)
    }
}

interface IWalker {
    void enterItem(item)
    void exitItem(item)
    void enterCommon(item)
    void exitCommon(item)
}

interface IWalkerFactory<T> {
    IWalker get(T obj)
}

abstract class AbstractWalker implements IWalker {
    void enterItem(item) { }
    void exitItem(item) { }
    void enterCommon(item) { }
    void exitCommon(item) { }
}

class OddWalker extends AbstractWalker {
    void enterItem(item) {
        println "Odd: $item"
    }
}

class EvenWalker extends AbstractWalker {
    void enterItem(item) {
        println "Even: $item"
    }
}

class WalkerFactory implements IWalkerFactory<Number> {
    @Lazy IWalker oddWalker = new OddWalker()
    @Lazy IWalker evenWalker = new EvenWalker()

    IWalker get(Number number) {
        if(number.isOdd()) oddWalker
        else evenWalker
    }
}
def巡检(IWalkerFactory工厂){ def列表=[1,2,3,4,5] 列出每个{ def walker=工厂。获取(it) walker.enterItem(it) walker.exitItem(it) } } 接口IWalker{ 无效项目(项目) 无效出口(项目) 无效(项目) 作废exitCommon(项目) } 接口IWalkerFactory{ IWalker get(T obj) } 抽象类AbstractWalker实现了IWalker{ 无效输入项(项){} 无效出口(项目){} 无效(项目){} 无效exitCommon(项目){} } 类OddWalker扩展了AbstractWalker{ 无效项目(项目){ println“奇数:$item” } } 类EvenWalker扩展了AbstractWalker{ 无效项目(项目){ println“偶数:$item” } } 类WalkerFactory实现IWalkerFactory{ @Lazy IWalker oddWalker=新oddWalker() @Lazy IWalker evenWalker=新evenWalker() IWalker获取(编号){ if(number.isOdd())oddWalker 艾尔斯伊文沃克 } } 简而言之,
walkeOver()
要求
IWalkerFactory
返回适合该项目的
IWalker
IWalkerFactory
实现是唯一关心偶数/奇数的代码。然后,
walkOver()
只调用由
IWalkerFactory
返回的
IWalker
上的方法


这种方法的一个好处是,它不再需要一个
复合程序
,它是策略和状态机的融合。如果您可以避免使用状态机,未来的开发人员将感谢您。

因此,当调用
common
方法时,它将引用
currentRef
中的当前引用?是的,它将调用委托上的任何方法,该方法在
this
中未被覆盖,实际上我无权访问
walkOver
方法(我模仿了另一个图书馆的行为)所以我不能改变它。是的,我也发现这个结构有点奇怪,但怀疑这不是故意的。