我在这个话题上搜索了很多,但我只找到了 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/