I have already implemented the DAO Pattern using
Abstract Factory Method.
At first implement an AbstractDAOFactory Interface
with the following methods: create(dsn, cfcroot), getDAOFactory(factoryType) and
specific abstract methods like getCustomerDAO(), getProductDAO()...
You also need to implement concrete DAO Factories
for supported databases or any other kind of persistence, i.e. MSSQL, ORACLE
and XML. These concrete DAO Factories will implement the abstract methods getCustomerDAO and getProductDAO
listed above.
Now you have to implement the DAOs itself. The
CustomerDAO should have the getCustomerById(), getAllCustomers(),
insertCustomer(), updateCustomer() and deleteCustomer() methods. ProductDAO have
similars methods.
Then, let me try to explain how it works. At
application level, you create an instance of the abstract DAOFactory, where you
call getDAOFactory("your_dsn", "MSSQL"). Based on the argument factoryType, the
abstract factory returns an concrete DAOFactory of that type, i.e. MSSQL. With
this concrete DAOFactory "in hands", you can get specific DAOs (i.e. Customers
or Products) for any supported datasource type.
Below are some example codes.
AbstractDAOFactory
<cfcomponent
displayname="AbstractDAOFactory">
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
this.cfcroot = "";
this.MSSQL = 1;
this.ORACLE = 2;
</cfscript>
<cffunction name="createDAOFactory" access="public" returntype="daofactory">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfargument name="cfcroot" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfset this.cfcroot = arguments.cfcroot>
<cfreturn this>
</cffunction>
<cffunction name="getDAOFactory"access="public" returntype="daofactory">
<!--- receive arguments --->
<cfargument name="factoryType" type="numeric" required="Yes">
<!--- set local vars --->
<cfset var returndaofactory = "">
<cfswitch _expression_="#arguments.factoryType#">
<cfcase value="1">
<cfinvoke component="#this.cfcroot#.dao.mssqldaofactory" method="createDAOFactory" returnvariable="returndaofactory" dsn="#this.dsn#" cfcroot="#this.cfcroot#">
</cfcase>
<cfcase value="2">
<cfinvoke component="#this.cfcroot#.dao.oracledaofactory" method="createDAOFactory" returnvariable="returndaofactory" dsn="#this.dsn#" cfcroot="#this.cfcroot#">
</cfcase>
</cfswitch>
<cfreturn returndaofactory>
</cffunction>
<cffunction name="getCustomerDAO" access="public" returntype="customerdao">
<cfabort showerror="This Method is Abstract and needs to be overridden">
</cffunction>
<cffunction name="getProductDAO" access="public" returntype="productdao">
<cfabort showerror="This Method is Abstract and needs to be overridden">
</cffunction>
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
this.cfcroot = "";
this.MSSQL = 1;
this.ORACLE = 2;
</cfscript>
<cffunction name="createDAOFactory" access="public" returntype="daofactory">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfargument name="cfcroot" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfset this.cfcroot = arguments.cfcroot>
<cfreturn this>
</cffunction>
<cffunction name="getDAOFactory"access="public" returntype="daofactory">
<!--- receive arguments --->
<cfargument name="factoryType" type="numeric" required="Yes">
<!--- set local vars --->
<cfset var returndaofactory = "">
<cfswitch _expression_="#arguments.factoryType#">
<cfcase value="1">
<cfinvoke component="#this.cfcroot#.dao.mssqldaofactory" method="createDAOFactory" returnvariable="returndaofactory" dsn="#this.dsn#" cfcroot="#this.cfcroot#">
</cfcase>
<cfcase value="2">
<cfinvoke component="#this.cfcroot#.dao.oracledaofactory" method="createDAOFactory" returnvariable="returndaofactory" dsn="#this.dsn#" cfcroot="#this.cfcroot#">
</cfcase>
</cfswitch>
<cfreturn returndaofactory>
</cffunction>
<cffunction name="getCustomerDAO" access="public" returntype="customerdao">
<cfabort showerror="This Method is Abstract and needs to be overridden">
</cffunction>
<cffunction name="getProductDAO" access="public" returntype="productdao">
<cfabort showerror="This Method is Abstract and needs to be overridden">
</cffunction>
</cfcomponent>
Concrete MSSQLDAOFactory
<cfcomponent displayname="MSSQLDAOFactory"
extends="abstractdaofactory">
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
this.cfcroot = "";
</cfscript>
<!--- creates the DAO Factory --->
<cffunction name="createDAOFactory" access="public" returntype="mssqldaofactory">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfargument name="cfcroot" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfset this.cfcroot = arguments.cfcroot>
<cfreturn this>
</cffunction>
<cffunction name="getCustomerDAO" access="public" returntype="mssqlcustomerdao">
<!--- set local vars --->
<cfset var customerDAO = "">
<cfinvoke component="#this.cfcroot#.dao.mssqlcustomerdao" method="createCustomerDAO" dsn="#this.dsn#" returnvariable="customerDAO ">
<cfreturn customerDAO>
</cffunction>
<cffunction name="getProductDAO" access="public" returntype="mssqlproductdao">
<!--- set local vars --->
<cfset var productDAO = "">
<cfinvoke component="#this.cfcroot#.dao.mssqlproductdao" method="createProductDAO" dsn="#this.dsn#" returnvariable="productDAO">
<cfreturn productDAO>
</cffunction>
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
this.cfcroot = "";
</cfscript>
<!--- creates the DAO Factory --->
<cffunction name="createDAOFactory" access="public" returntype="mssqldaofactory">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfargument name="cfcroot" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfset this.cfcroot = arguments.cfcroot>
<cfreturn this>
</cffunction>
<cffunction name="getCustomerDAO" access="public" returntype="mssqlcustomerdao">
<!--- set local vars --->
<cfset var customerDAO = "">
<cfinvoke component="#this.cfcroot#.dao.mssqlcustomerdao" method="createCustomerDAO" dsn="#this.dsn#" returnvariable="customerDAO ">
<cfreturn customerDAO>
</cffunction>
<cffunction name="getProductDAO" access="public" returntype="mssqlproductdao">
<!--- set local vars --->
<cfset var productDAO = "">
<cfinvoke component="#this.cfcroot#.dao.mssqlproductdao" method="createProductDAO" dsn="#this.dsn#" returnvariable="productDAO">
<cfreturn productDAO>
</cffunction>
</cfcomponent>
MSSQLProductDAO
<cfcomponent displayname="MSSQLProductDAO"
extends="productdao">
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
</cfscript>
<!--- createProductDAO --->
<cffunction access="public" name="createProductDAO" returntype="mssqlproductdao">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfreturn this>
</cffunction>
<!--- insertProduct --->
<cffunction name="insertProduct " access="public" returntype="string">
<!--- receive arguments --->
<cfargument name="productId" required="Yes" type="string">
<cftry>
<cfquery datasource="#this.dsn#">
INSERT INTO
VALUES ()
</cfquery>
<cfcatch type="Any">
<cfthrow errorcode="001" message="Error in method insertProduct :<br>#CFCATCH.Message#">
</cfcatch>
</cftry>
<cfreturn arguments.productId>
</cffunction>
<!--- updateProduct --->
<cffunction name="updateProduct" access="public" returntype="string">
<!--- receive arguments --->
<cfargument name="productId" required="Yes" type="string">
<cfargument name="label" required="Yes" type="string">
<cftry>
<cfquery datasource="#this.dsn#">
UPDATE
<!--- pseudo constructor --->
<cfscript>
this.dsn = "";
</cfscript>
<!--- createProductDAO --->
<cffunction access="public" name="createProductDAO" returntype="mssqlproductdao">
<!--- receive arguments --->
<cfargument name="dsn" type="string" required="Yes">
<cfset this.dsn = arguments.dsn>
<cfreturn this>
</cffunction>
<!--- insertProduct --->
<cffunction name="insertProduct " access="public" returntype="string">
<!--- receive arguments --->
<cfargument name="productId" required="Yes" type="string">
<cftry>
<cfquery datasource="#this.dsn#">
INSERT INTO
VALUES ()
</cfquery>
<cfcatch type="Any">
<cfthrow errorcode="001" message="Error in method insertProduct :<br>#CFCATCH.Message#">
</cfcatch>
</cftry>
<cfreturn arguments.productId>
</cffunction>
<!--- updateProduct --->
<cffunction name="updateProduct" access="public" returntype="string">
<!--- receive arguments --->
<cfargument name="productId" required="Yes" type="string">
<cfargument name="label" required="Yes" type="string">
<cftry>
<cfquery datasource="#this.dsn#">
UPDATE
SET label =
'#arguments.label#',
WHERE productd = '#arguments.productId#'
</cfquery>
<cfcatch type="Any">
<cfthrow errorcode="002" message="Error in method updateProduct:<br>#CFCATCH.Message#">
</cfcatch>
</cftry>
<cfreturn arguments.productId>
</cffunction>
</cfcomponent>
WHERE productd = '#arguments.productId#'
</cfquery>
<cfcatch type="Any">
<cfthrow errorcode="002" message="Error in method updateProduct:<br>#CFCATCH.Message#">
</cfcatch>
</cftry>
<cfreturn arguments.productId>
</cffunction>
</cfcomponent>
Business Object: ProductManager.cfc
<cfcomponent
displayname="ProductManager">
<cfproperty
name="myProductDAO" type="ProductDAO">
<!--- pseudo constructor --->
<cfscript>
this.myProductDAO = CreateObject("component", "#your_cfcroot#.dao.DAOFactory).createDAOFactory("your_dsn", "your_cfcroot").getDAOFactory("MSSQL").getProductDAO()>
</cfscript>
<!--- getProduct --->
<cffunction access="public" name="createProduct" returntype="product">
<!--- receive arguments --->
<cfargument name="productId" type="string" required="Yes">
<cfreturn this.myProductDAO.getProductById(productId: arguments.productId)>
</cffunction>
</cfcomponent>
this link explains the pattern at all and was used
as reference: http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
Of course there are some diferences from one
implementation in Java and CFC.
I hope this can help as a starting
point.
[]'s
Aldo d'Aquino
----- Original Message -----
From: "Nathan Dintenfass" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, October 15, 2003 5:48 PM
Subject: RE: [CFCDev] Calling another CFC from within a method
> CFC you can call them as local variables. So, you can do things like:
>
>
> <cfcomponent>
> <cffunction name="getStuff">
> <cfreturn "stuff">
> </cffunction>
>
> <cffunction name="getFoo">
> <cfset myStuff = getStuff()>
> </cffunction>
> </cfcomponent>
>
> You can also use CFINVOKE, but you don't need the COMPONENT attribute if
> calling a method of the same CFC.
>
>
>
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
> > Behalf Of Nando
> > Sent: Wednesday, October 15, 2003 5:05 AM
> > To: [EMAIL PROTECTED]
> > Subject: [CFCDev] Calling another CFC from within a method
> >
> >
> > I'm working on my first DAO object and was wondering if there is a
> > recommended practice for calling another cfc from within a method of an
> > object, along the lines of using cfinvoke or CreateObject or ...
> >
> >
>
> ----------------------------------------------------------
> You are subscribed to cfcdev. To unsubscribe, send an email
> to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev'
> in the message of the email.
>
> CFCDev is run by CFCZone (www.cfczone.org) and supported
> by Mindtool, Corporation (www.mindtool.com).
>
> An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]
>
