Как добавить общие действия в контроллеры, не используя наследование? - PullRequest
3 голосов
/ 30 ноября 2009

Мне нужно добавить общие действия ко многим моим контроллерам без использования наследования. Все наши контроллеры расширяют абстрактный контроллер, и функциональность, которую я хочу включить, не имеет смысла в абстрактном контроллере.

Моя первоначальная идея состояла в том, чтобы использовать Mixin, но, похоже, что действия, поскольку они являются замыканиями, не являются "смешанными" с контроллерами, которые включают в себя mixin, только методы.

Кто-нибудь может предложить, как я могу получить "смешанную" функциональность для добавления действий в контроллеры?

спасибо!

Ответы [ 4 ]

7 голосов
/ 01 декабря 2009

Все наши контроллеры расширяют абстрактный контроллер и функциональность я включать не имеет смысла в абстрактный контроллер.

Тогда почему бы не иметь второй абстрактный контроллер, который расширяет базовый контроллер и, в свою очередь, расширяется только теми контроллерами, которым требуется эта функциональность?

Это звучит как самое простое и чистое решение для меня - конечно, лучше, чем использование метапрограммирования. «Предпочитать композицию наследованию» не означает, что наследование является фундаментально грязной вещью, которую следует избегать любой ценой.

6 голосов
/ 01 декабря 2009

Способ сделать это - перебрать ваши контроллеры и добавить к ним методы, используя метапрограммирование.

Для одного примера, проверьте плагин perf4j (файл Perf4jGrailsPlugin.groovy).

В нем вы увидите что-то вроде:

application.controllerClasses.each() {
            addPerf4jMethods(it.clazz, log)
        } 

def addPerf4jMethods(artefactClass, log) {
        log.info "Adding Per4j methods: ${artefactClass}..."


        artefactClass.metaClass.withStopwatch << { Closure callable ->
            withStopwatch("", null, callable)
        }

        artefactClass.metaClass.withStopwatch << { String tag, Closure callable ->
            withStopwatch(tag, null, callable)
        } 
}

В приведенном выше коде вы перебираете все контроллеры и добавляете методы с помощью StopWatch, так что теперь они доступны везде. Если вам нужно сделать это только на некоторых контроллерах, вы, очевидно, можете выполнить дополнительные проверки.

Вы можете поместить этот код в BootStrap.groovy, чтобы он запускался при каждом запуске приложения.

2 голосов
/ 01 декабря 2009

Третий вариант, который я часто использую в подобных ситуациях, - это статический импорт. На самом деле это часть Java (не отличная), о которой многие люди не знают.

Итак, если у вас есть такой класс со статическими методами, которыми вы хотите поделиться:

class Foo {
    static baz = { -> 
        return "baz!"
    }
}   

И используйте «import static» в классах, для которых вы хотите, чтобы этот метод был доступен:

import static Foo.baz

class Bar {
    static void main(String[] args) {
        assert "baz!" == baz.call()
    }
}

Никакой магии суперкласса или миксина не требуется, пусть компилятор сделает всю работу за вас.

1 голос
/ 26 декабря 2010

Согласно новому Grails плагин динамического контроллера , это:

позволяет динамически создавать контроллеры и добавлять действия к существующим контроллерам

с использованием миксинов.

Кажется, он соответствует вашим требованиям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...