我有一个方法,需要某个类作为参数。
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)
}
}
}
我希望我的CompositeWalker
将walkOver
方法中方法的所有后续调用委托给相应的对象。
目前,我存储了对当前对象的引用,只是调用了它的方法。
理想情况下,我想做这样的事情
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
内部实现evenWalker
和compositeWalker
的方法。
是否可以做这样的事情?
答案 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
返回适合该项目的IWalker
。 IWalkerFactory
实现是唯一关心偶数/奇数的代码。然后,walkOver()
只会调用IWalker
返回的IWalkerFactory
上的方法。
这种方法的一个好处是它不需要CompositeWalker
,它是策略和状态机的融合。如果你可以避免使用状态机,未来的开发人员会感谢你。