Factory methods are responsible for manufacturing objects.
From ‘Gang of Four’:
‘Frameworks use abstract classes to define and maintain relationships between objects. A framework is often responsible for creating these objects as well’
Coldspring as a framework has an excellent implementation of the Factory Method pattern.
Example:
Let’s say I am building an application that has ‘CDs’ as objects.
If I am using a Service / Gateway / DAO pattern in my application… (I know that many folks rail against the 5:1 approach, but let’s just say for sake of argument that transfer is not a good fit for this application.), I have quite a bit of code to write just to get to a point where all of my required objects are instantiated:
<cfset datasource="library">
<cfset cdBean = createObject("component", "extensions.com.jimrising.cd.cd").init(title: "Joshua Tree", artist: "U2")>
<cfset cdDAO = createObject("component", "extensions.com.jimrising.cd.cdDAO").init(dsn: #datasource#)>
<cfset cdGateway = createObject("component", "extensions.com.jimrising.cd.cdGateway").init(dsn: #datasource#)>
<cfset cdService = createObject("component", "extensions.com.jimrising.cd.cdService").init(cdDAO: cdDAO, cdGateway: cdGateway)>Note that the ‘cdService’ depends on the injection of the cdGateway and cdDAO. Coldspring handles this dependency injection nicely as well.
In order for me to create a new ‘cd’, and then save it to the database:
<cfset cdService.save(cdBean)>
The issue is one of persistence. In order for me to use these objects throughout my application, without the Factory Method, I would need to instantiate them each time I needed them. Using the Factory Method and a little setup within Coldspring, these objects persist and I’m able to access them through the factory, without needing to know all of the dependencies or subclasses:
<cfset application.serviceFactory.cdBean.init(title: "Joshua Tree", artist: "U2")> <cfset application.serviceFactory.cdService.save(cdBean)>
Note that the DAO, Service, and Bean have already been instantiated, and so saving a new ‘cd’ object to the database (from anywhere within your application) is a simple matter of building the bean and saving it through the service within the serviceFactory.
Here is what the XML configuration (services.xml) looks like for ColdSpring:
<beans> <bean id="cdGateway" class="extensions.com.jimrising.cd.cdGateway"> <constructor-arg name="dsn"><value>${dsn}</value></constructor-arg> </bean> <bean id="cdDAO" class="extensions.com.jimrising.cd.cdDAO"> <constructor-arg name="dsn"><value>${dsn}</value></constructor-arg> </bean> <bean id="cdService" class="extensions.com.jimrising.cd.cdService"> <constructor-arg name="cdDAO"><ref bean="cdDAO" /></constructor-arg> <constructor-arg name="cdGateway"><ref bean="cdGateway" /></constructor-arg> </bean> <bean id="cdBean" class="extensions.com.jimrising.cd.cd" /> </beans>
And the simple one time instantiation of the serviceFactory within your application.cfc onRequestStart() method:
<cfset application.defaultProperties.dsn = "myDsn"/>
<cfset application.serviceFactory = createObject('component','coldspring.beans.DefaultXmlBeanFactory').init(structnew(),application.defaultProperties)/>
<cfset application.serviceDefinitionLocation = expandPath('/config/services.xml')>
<cfset application.serviceFactory.loadBeansFromXmlFile(application.serviceDefinitionLocation)/>