如何使用Grails服务层实现多态行为

时间:2014-10-13 14:55:30

标签: grails service polymorphism service-layer

我在这个主题上搜索了很多内容,但我只发现了this Stackoverflow帖子。假设我有一个简单的域模型层次结构:

class Furniture{}
class Table extends Furniture{}
class Sideboard extends Furniture{}

如何实现一个名为position的服务方法,该方法在不使用instanceof的情况下为相应的对象类型调用,或者为.class.name实现if语句,同时仍为其维护单独的服务类各种域类?

我非常喜欢this回答,但这里所有方法都包含在一个服务中。我认为服务类可能会变得太大,这取决于要执行的操作数或类层次结构的深度(我知道,无论如何都应该避免后者,但仍然如此)。

我可以想到两种方法来实现这一目标,但它们看起来都很破碎和黑客。

选项1:访问应用程序上下文

class FurnitureService{
    def grailsApplication
    void position(Furniture furniture){
       grailsApplication.getMainContext().getBean(Introspector.decapitalize(furniture.class.simpleName) +  'Service').position(furniture)
    }
}
class TableService{
    void position(Table table){
        println "table positioned"
    }
}
class SideboardService{
    void position(Sideboard sideboard){
        println "sideboard positioned"
    }
}

我真的很讨厌这个解决方案,因为它根本没有使用DI。

选项2:使用反射来获得正确的注入服务类

class FurnitureService{
    def tableService
    def sideboardService
    void position(Furniture furniture){   
        furniture.class.getDeclaredField(Introspector.decapitalize(furniture.class.simpleName) + 'Service').get(this).position(furniture)
    }
}
class TableService{
    void position(Table table){
        println "table positioned"
    }
}
class SideboardService{
    void position(Sideboard table){
        println "sideboard positioned"
    }
}

不知道第一个选项是否更好,或者这个选项是否更糟糕。我不喜欢用反射。在传统的面向对象方式中,我只是覆盖一个抽象方法。 必须是处理该问题的最佳惯例约定。

我想我现在正用这些方法过度努力。任何人都可以给我一个干净,简洁的商业标准"解?如果有人认为有必要,我将不会被冒犯,如果重定向到grails文档或教程。

1 个答案:

答案 0 :(得分:1)

如果您拥有来自不同服务的所有给定方法,那么您的传入类型可以决定使用哪种方法。有不同的方法可以将所有服务混合成一个。

您可以使用@Delegate并让它全部决定传入类型。 E.g:

class Furniture{}
class Table extends Furniture{}
class Sideboard extends Furniture{}
class FurnitureService{
    @Delegate TableService tableService
    @Delegate SideboardService sideboardService
}
class TableService{
    String position(Table table){
        return 'table'
    }
}
class SideboardService{
    String position(Sideboard sideboard){
        return 'sideboard'
    }
}

def s = new FurnitureService()
assert s.position(new Table())=='table'
assert s.position(new Sideboard())=='sideboard'

基本相同,如果您的groovy / grails版本足够新,可以使用traits完成:

class Furniture{}
class Table extends Furniture{}
class Sideboard extends Furniture{}
class FurnitureService implements TableService, SideboardService {}
trait TableService{
    String position(Table table){
        return 'table'
    }
}
trait SideboardService{
    String position(Sideboard sideboard){
        return 'sideboard'
    }
}

def s = new FurnitureService()
assert s.position(new Table())=='table'
assert s.position(new Sideboard())=='sideboard'

当然,这只是从特殊服务中组成通用服务的所有技巧。简单的事实是,传入的参数将决定,将调用哪种专用方法是关键。