26

現在、異なるコントローラー間などでメソッドを共有する必要がある場合はprocessParams(params)、継承またはサービスを使用します。どちらのソリューションにもいくつかの不便があります:

  • 継承では、多重継承を使用できません。つまり、すべてのコントローラー ユーティリティ メソッドを 1 か所に配置する必要があります。また、grails には、開発モードで Base Controller クラスのコード変更を検出しないバグがあります (アプリを再起動する必要があります)。
  • サービスでは、params、session、flush などの注入されたすべてのプロパティにアクセスすることはできません...

だから私の質問は:複数のコントローラにアクセス可能ないくつかの一般的なメソッドを使用する他の方法はありますか?

4

5 に答える 5

22

私が気に入っているオプションの 1 つは、一般的なメソッドをカテゴリとして記述し、必要に応じてそれをコントローラーに混在させることです。継承よりもはるかに柔軟性があり、params などにアクセスでき、コードはシンプルでわかりやすいものです。

ここに小さな例があります:

@Category(Object)
class MyControllerCategory {
    def printParams() {
        println params
    }
}

@Mixin(MyControllerCategory)
class SomethingController {

    def create = {
        printParams()
        ...
    }

    def save = {
        printParams()
    }
}
于 2010-11-16T17:26:44.443 に答える
3

共通の機能は新しいクラスの呼び出しであり、必ずしも共通の祖先ではありません。質問の定式化には、それに対する責任の説明がありません。言うまでもなく、新しいクラスを作成するのは単一の責任です。クラスの責任に基づいて、さらに決定を下します。

私はrobbbertJaredの答えのハイブリッドを好みます。追加のクラスを作成し、必要なコントローラー内部をパラメーターとして渡します。メソッド オブジェクトからクラスが開発されることもあります。お気に入り:

def action = {
  def doer = SomeResponsibilityDoer(this.request, this.response)
  render doer.action()
}

それほど簡潔ではありませんが、テスト中のコードを取得し、結合を低く保つことができます。

いくつかのフィールドしかないのでSomeResponsibilityDoer、応答を要求します。すべての要求でそれを構築するのは大したことではありません。

SomeResponsibilityDoerまた、次の理由により、dev でコントローラーの変更をリロードしないことも大したことではありません。

  1. 最初は、一部のコントローラー ファイルで宣言できます。再ロードされます。完了したら、頻繁に変更されないことを願っていますので、 に移動しsrc/groovyます。
  2. さらに重要なことは、アプリケーションを実行してコントローラーをリロードするよりも、単体テストの下で設計を開発する方が速くて優れているということです。
于 2010-11-23T14:17:38.887 に答える
3

これは、開発モードでの再起動の問題には役立ちませんが、私がこの問題を解決した方法です。これは醜く、おそらく良い習慣ではありませんが、一般的なコードをクロージャーとしてクラスに分解します。次に、次のようなことができます。

new ControllerClosures().action(this)

そして、controllerClosures クラスの with から

def action={
    it.response.something
    return [allYourData]
}
于 2010-11-16T15:09:38.713 に答える
2

委任設計パターンを使用できます。

class Swimmer {
    def swim() { "swimming" }
}

class Runner {
    def run() { "running" }
}

class Biker {
    def bike() { "biking" }
}

class Triathlete { 
    @Delegate Swimmer swimmer
    @Delegate Runner runner
    @Delegate Biker biker
}

def triathlete = new Triathlete(
    swimmer: new Swimmer(),
    runner: new Runner(),
    biker: new Biker()
)

triathlete.swim()
triathlete.run()
triathlete.bike()

コントローラーの場合、ヘルパー クラスをインスタンス フィールド (または nullary コンストラクター) に直接割り当てます。

class HelperClass {
    def renderFoo() { render 'foo' }
}

class FooController {
    private @Delegate HelperClass helperClass = new HelperClass()

    def index = { this.renderFoo() }
}

delegateの型情報は、それを含むクラスにコンパイルされます。

于 2010-11-16T15:22:41.633 に答える
1

すべての共通メソッドを commonService に記述し、そのサービスを使用して共通メソッドを呼び出すことができます

于 2013-05-14T10:27:04.313 に答える