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

时间:2016-04-27 11:48:37

标签: 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 {
            instance.enterEven(it)
            instance.exitEven(it)
        }
        instance.exitItem(it)
    }
}

基本上我遍历列表并使用其元素执行某些操作。

班级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) { }
}

我有两个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)
        }
    }
}

我希望我的CompositeWalkerwalkOver方法中方法的所有后续调用委托给相应的对象。

目前,我存储了对当前对象的引用,只是调用了它的方法。

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

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
    }
}

我根本没有在oddWalker内部实现evenWalkercompositeWalker的方法。

是否可以做这样的事情?

2 个答案:

答案 0 :(得分:1)

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

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
    }
}

答案 1 :(得分:1)

对我来说,关于你的代码还有些不对劲。请注意,您已拨打isOdd()两次:walkOver()CompositeWalker。所以你基本上做了两次同样的决定。此外,IWalker中的偶数/奇数对及其相应的偶数/奇数实现是一个线索,表明您使用策略模式的方式可能存在缺陷。

CompositeWalker委托给适当的IWalker时,我认为这是更好的方式;根据我对你的代码的理解。我建议使用工厂选择合适的步行器进行重构,并让步行者完全无视物品是偶数还是奇数;因为已经做出了选择。所以这就是:

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
    }
}

简而言之,walkeOver()要求IWalkerFactory返回适合该项目的IWalkerIWalkerFactory实现是唯一关心偶数/奇数的代码。然后,walkOver()只会调用IWalker返回的IWalkerFactory上的方法。

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