I have googled a lot on that topic, but I only found this Stackoverflow post. Assuming I have a simple domain model hierarchy as such:
class Furniture{}
class Table extends Furniture{}
class Sideboard extends Furniture{}
How can I implement a service method called position
that is called for the corresponding object type without using instanceof
or an if-statement with .class.name
while still maintaining separated service classes for the various domain classes?
I really like this answer, but here all methods are packed in one service. I think the service class may grow too large depending on the number of operations to be performed or the depth of the class hierarchy (I know, the latter should be avoided anyway, but still).
I can think of two ways of achieving that by myself, but they both seem broken and hackish.
Option 1: Accessing Application Context
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"
}
}
I really hate that solution, because it does not make use of DI at all.
Option 2: Use reflection to get the right injected service class
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"
}
}
No idea if the first option is better or if this one is just more terrible. I don't like to use reflection. In a traditional OO manner, I would just override an abstract method. There must be a best-practice convention to handle that.
I guess I am making my life way too hard right now with those approaches. Can anybody give me a clean, concise "business standard" solution? I will not be offended if redirected to the grails documentation or a tutorial, if one thinks that is necessary.