2016-04-27 4 views
1

私は、あるクラスをパラメータとして必要とするメソッドを持っています。別のオブジェクト参照へのすべての後続の呼び出しを委任する

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は、私が唯一の特定のタスクを実行IWalkerの2つの基本サブクラスを持ってこの

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

私は複合歩行器を持っている - に操作を委譲すべき対応するインスタンス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メソッド内のメソッドのすべての後続の呼び出しを委譲します。

現在、私は現在のオブジェクトへの参照を保存し、そのメソッドを呼び出すだけです。

理想的には私があり、私は全くcompositeWalkeroddWalkerevenWalkerのメソッドを実装していないこの

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

ような何かをしたいと思います。

このようなことは可能ですか?

答えて

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

したがって、 'common'メソッドを呼び出すときに' currentRef'の現在の参照を参照しますか? – lapots

+0

はい、それは 'this'でオーバーライドされていないデリゲートのメソッドを呼び出します – loteq

1

私にとって、あなたのコードに関するものはありません。 isOdd()walkOver()CompositeWalkerに2回呼び出していることに注目してください。したがって、本質的に同じ決定を2回行うことになります。また、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()は、アイテムのための適切なのですIWalkerを返すようにIWalkerFactoryを要求します。 IWalkerFactoryの実装は、偶数/奇数を扱う唯一のコードです。次に、walkOver()IWalkerFactoryによって返されたIWalkerのメソッドを呼び出します。

このアプローチの利点は、戦略とステートマシンの融合であるCompositeWalkerの必要性がなくなることです。ステートマシンを使用することを避けることができれば、将来の開発者はあなたに感謝します。

+1

実際には' walkOver'メソッドにアクセスできません(私は別のライブラリの動作を模倣しました)ので変更できません。 – lapots

+0

はい私はあまりにも奇妙な構造を見つけましたが、意図的ではないと思われました。 – loteq

関連する問題