Friday 15 March 2013

How to achieve Polymorphic behaviour with the Grails Service Layer -



How to achieve Polymorphic behaviour with the Grails Service Layer -

i have googled lot on topic, found this stackoverflow post. assuming have simple domain model hierarchy such:

class furniture{} class table extends furniture{} class sideboard extends furniture{}

how can implement service method called position called corresponding object type without using instanceof or if-statement .class.name while still maintaining separated service classes various domain classes?

i this answer, here methods packed in 1 service. think service class may grow big depending on number of operations performed or depth of class hierarchy (i know, latter should avoided anyway, still).

i can think of 2 ways of achieving myself, both seem broken , 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 hate solution, because not create utilize of di @ all.

option 2: utilize reflection 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 thought if first alternative improve or if 1 more terrible. don't utilize reflection. in traditional oo manner, override abstract method. there must best-practice convention handle that.

i guess making life way hard right approaches. can give me clean, concise "business standard" solution? not offended if redirected grails documentation or tutorial, if 1 thinks necessary.

if have given methods different services, incoming type of furnture decide, 1 use. there different ways mixin services one.

you utilize @delegate , allow decide on passed in type. 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){ homecoming 'table' } } class sideboardservice{ string position(sideboard sideboard){ homecoming 'sideboard' } } def s = new furnitureservice() assert s.position(new table())=='table' assert s.position(new sideboard())=='sideboard'

basically same, if groovy/grails version new enough, can done traits:

class furniture{} class table extends furniture{} class sideboard extends furniture{} class furnitureservice implements tableservice, sideboardservice {} trait tableservice{ string position(table table){ homecoming 'table' } } trait sideboardservice{ string position(sideboard sideboard){ homecoming 'sideboard' } } def s = new furnitureservice() assert s.position(new table())=='table' assert s.position(new sideboard())=='sideboard'

this of course of study groovy magic compose generic service special ones. simple fact, passed in param decide, specialized method called key here.

grails service polymorphism service-layer

No comments:

Post a Comment