observer design pattern in coldfusion
The observer design pattern is used in application development to observe the state of an object. The best way to think about it is the publish / subscribe model. In this pattern you have one object that is being observed (the subject), and a group of objects watching the subject called observers or listeners. This pattern is an excellent example of loose coupling, because our classes can interact with very little knowledge of each other.
(read about the pattern @ http://en.wikipedia.org/wiki/Observer_pattern )
This post will demonstrate the usage of this pattern in ColdFusion
In the example I am creating a user list and the list if being watched by a logging observers that prints the message out to the browser anytime the new user gets added
IObservable.cfc
The Object that will provide notification to registered observers/listeners needs to implement this interface, in our case it will be UserList.cfc
<cfinterface><cffunction name="registerObserver"><cfargument name="observer" type="any"></cffunction><cffunction name="unregisterObserver"><cfargument name="observer" type="any"></cffunction><cffunction name="notifyObservers"><cfargument name="args" type="any"></cffunction></cfinterface>- Download this code: IObservable.cfc
IObserver.cfc
The Object that will recieve notifications has to implement this interface, in our case it will be UserListLogger.cfc
<cfinterface><cffunction name="getInstanceID" returntype="String"/><cffunction name="onChanged"><cfargument name="sender" type="any"><cfargument name="args" type="any"></cffunction></cfinterface>- Download this code: IObserver.cfc
UserList.cfc
This Class implements the IObservable interface
<cfcomponent implements="IObservable"><cfscript>variables._observers = StructNew();</cfscript><cffunction name="addCustomer"><cfargument name="name"><!--- perform some action ---><cfset notifyObservers(arguments.name)></cffunction><cffunction name="registerObserver"><cfargument name="observer" type="any"><cfif not StructKeyExists(variables._observers,arguments.observer.getInstanceID())><cfset StructInsert(variables._observers, arguments.observer.getInstanceID(), arguments.observer)></cfif></cffunction><cffunction name="unregisterObserver"><cfargument name="observer" type="any"><cfif StructKeyExists(variables._observers,arguments.observer.getInstanceID())><cfset StructDelete(variables._observers, arguments.observer.getInstanceID())></cfif></cffunction><cffunction name="notifyObservers"><cfargument name="args"><cfloop collection="#variables._observers#" item="key"><cfset observer = StructFind(variables._observers, key)><cfset observer.onChanged(this, arguments.args)></cfloop></cffunction></cfcomponent>- Download this code: UserList.cfc
UserListLogger.cfc
This Class implements the IObserver interface and at present only displays the information on browser
<cfcomponent implements="IObserver"><cfset variables.instanceID = CreateUUID() ><cffunction name="getInstanceID" returntype="String"><cfreturn variables.instanceID></cffunction><cffunction name="onChanged"><cfargument name="sender" type="any"><cfargument name="args" type="any"><cfoutput><b>#arguments.args#</b> added to the user list<br></cfoutput></cffunction></cfcomponent>- Download this code: UserListLogger.cfc
test.cfm
The code here creates a UserList and registers the UserListLogger with it. The remaining part of the code adds user to the list and as soon the user is add, the UserListLogger gets notification of change.
<cfset userList = CreateObject("component","UserList")><cfset userList.registerObserver(CreateObject("component", "UserListLogger"))><cfset userList.addCustomer( "Arjun" )><cfset userList.addCustomer( "Vivaan" )>- Download this code: test.cfm
The output of test.cfm will look like this
Arjun added to the user list
Vivaan added to the user list
Something worth watching is how the loose coupling of components, the UserList does not know what UserListLogger is doing or going to do with the notification. In fact there can be multiple listeners attached with UserList e.g. listeners to perform data base insert, listeners for email notification etc. The UserList does not care about how many or what type of listeners is attached to it, instead it just focuses on its task of notifying to the registered listeners about the change.
As you can see by following this pattern we can create ColdFusion applications that can adapt to changes and is easily maintainable.
1 comment April 14th, 2008