26

目前,当我需要processParams(params)在不同控制器之间共享方法时,我使用继承或服务。这两种解决方案都有一些不便之处:

  • 使用继承,您不能使用多重继承,这意味着您需要将所有控制器实用程序方法放在一个地方。此外,grails 中存在一个错误,在开发模式下未检测到 Base Controller 类中的任何代码更改(您需要重新启动应用程序)
  • 使用服务,您无法访问所有注入的属性,如参数、会话、刷新......

所以我的问题是:有没有其他方法可以使用多个控制器可以访问的一些常用方法?

4

5 回答 5

22

我喜欢的一个选择是将常用方法编写为一个类别,然后根据需要将其混合到控制器中。它比继承提供了更多的灵活性,可以访问参数之类的东西,并且代码简单易懂。

这是一个小例子:

@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,因为:

  1. 最初,您可以在一些控制器文件中声明它——它将被重新加载。完成后,希望它不会经常更改,因此将其移至src/groovy.
  2. 更重要的是,在单元测试下进行设计开发比在应用程序运行和重新加载控制器下开发更快更好。
于 2010-11-23T14:17:38.887 回答
3

这无助于您在开发模式下重新启动的问题,但这是我解决此问题的方式。这是丑陋的,可能不是好的做法,但我将通用代码作为闭包放入类中。然后我可以做类似的事情:

new ControllerClosures().action(this)

并从控制器闭包类中

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

委托的类型信息被编译到包含类中。

于 2010-11-16T15:22:41.633 回答
1

您可以在 commonService 中编写所有常用方法并使用该服务来调用常用方法

于 2013-05-14T10:27:04.313 回答