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

标签 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:使用反射获取正确的注入(inject)服务类
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"
    }
}

不知道第一个选项是否更好,或者这个选项是否更糟糕。我不喜欢使用反射。在传统的 OO 方式中,我只会重写一个抽象方法。必须有一个最佳实践约定来处理这个问题。

我想我现在用这些方法让我的生活变得太艰难了。谁能给我一个干净、简洁的“商业标准”解决方案?如果有人认为有必要,我不会被重定向到 grails 文档或教程。

最佳答案

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

您可以使用 @Delegate 并让它全部决定传入的类型。例如:

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'

这当然是从特殊服务中组合通用服务的绝妙魔法。简单的事实,传入的参数将决定调用哪个专门的方法是这里的关键。

关于grails - 如何使用 Grails 服务层实现多态行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26342917/

相关文章:

grails - Grails-检查项目是否具有父项

android - 从服务接收触摸事件(解决方案?)

symfony - 使用 Symfony 4.1.3 声明服务时如何从 Autowiring 中排除域?

java - Java 中能否自动将一个类的对象转换为子类并调用重载方法?

c++ - 子类中的编辑函数

grails - hasMany 和 hasOne 在 Grails 中如何工作?

javascript - 如何禁用grails插件的资源

安卓定时任务

java - 我可以在java中访问类之外的 protected 字段

grails - Grails 3升级后的致命缓慢性能