我在这个主题上搜索了很多内容,但我只发现了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文档或教程。
答案 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'
当然,这只是从特殊服务中组成通用服务的所有技巧。简单的事实是,传入的参数将决定,将调用哪种专用方法是关键。