How to separate interface from implementation in G

2019-03-18 01:47发布

I was wondering if it's possible to create a service interface on Grails and I can't find a proper way of doing it. This explanation isn't satisfactory, since it seems to mix Java and Groovy:

http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html

It seems to me like a bad design flaw of the framework, given that the interface mechanism is one of the best features of Java (and most OO languages).

Any idea to clarify this issue?

Thanks! Mulone

4条回答
Fickle 薄情
2楼-- · 2019-03-18 02:07

The best solution I found for this is using Spring bean aliases. Basically you need to:

1) Create an interface in src/groovy ( MyService.groovy )

2) Inject your service wherever you need it:

class MyController {
    MyService myService
}

3) Create your regular services implementing that interface ( ImplOneService.groovy, ImplTwoService.groovy )

4) Add an entry to resources.groovy where you define which implementation to use (eventually, testing for environment, or anything else you need):

beans = {
    if (...development, useFTP, etc...) {
        springConfig.addAlias 'myService', 'ImplOneService'
    } else {
        springConfig.addAlias 'myService', 'ImplTwoService'
    }
}

Complete sources here

My comments: Using interfaces in groovy really seems like some kind of "I want to stick with some java stuff I'm more comfortable with". In this case, strong-typing. But it's exactly the nice part of groovy saying "No worries, you can keep the java way if you want".

查看更多
神经病院院长
3楼-- · 2019-03-18 02:19
  • Define the service interface in a class com.mycompany.mypackage.MyInterface.groovy stored under src/groovy
  • Define the service implementation stored under grails-app/services

    class MyService implements MyInterface {
        // service implementation goes here
    }
    
查看更多
爷的心禁止访问
4楼-- · 2019-03-18 02:19

Its not a design flaw. Groovy is different than java in that it is a dynamic language that uses 'duck-typing'. Whats interesting in groovy is that there are also interfaces. So if you follow @don's suggestion, you can make sure that your service conforms to the interface, but the way you do DI with grails is to just specify the service implementation. i.e. you do not get the compile time check where you use the service implementation, like you do in java.

Note that there is no tight coupling here. Coupling implies that something is bound to a type. But with groovy's loose typing system, types are essentially dynamic creatures. So in java, if you declare a type to be a specific implementation, the code might not compile if you change the type later. In groovy, the code will always compile if you use the 'def'...(I think this is correct)

查看更多
迷人小祖宗
5楼-- · 2019-03-18 02:22

You can have an interface, but actually you don't need one. If I understand you correctly you would like to have two implementations of a service and be able to choose which one to use.

Simply implement two services named for example MyService1 and MyService2, then in grails-app/conf/spring/resource.groovy you can specify:

beans = {
    ... 
    // syntax is beanId(implementingClassName) { properties }
    myService(MyService1)
    ...
}

or even:

beans = {
    ...
    if (someConfigurationOption) {
        myService(MyService1)
    } else {
        myService(MyService2)
    }
}

This is how you tell Spring which service to actually inject for myService. Now you will be able to use myService like:

public MyController {
    def myService
    ...
}

and Spring will auto wire a proper implementation. This allows you to configure which service implementation to use based for example on some configuration.

查看更多
登录 后发表回答