Posts with the tag 'design pattern'


Strategy Design Pattern in Coldfusion

In this blog post I will demonstrate the practical use of strategy design pattern in ColdFusion and discuss other possibilities.

So what is Strategy Design Pattern?
Wikipedia : “In computer programming, the strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms can be selected at runtime.
Gang of four : “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

So from the various descriptions it’s clear that this pattern can be used in the situation where there is possibility of having difference/multiple calculation and the application has to choose the right one on the fly.

I am going to use a scenario to build the case on why and how this pattern should be used.

Scenario:

Let’s say there is a web application which has multiple developers working on it, or have multiple teams working on independent section of the application, in such sort of application its fundamental to have core set of components that the developer use and there is also a possibility that they may be used across multiple applications. In such sort of scenario its inherent that core component be stable and least amount of changes should be done on the core components (i.e. cfc’s ) to avoid large scale impacts to other modules/developers.

So let’s say one of the core components that we have is the Customer.cfc it has some properties and also methods which get used by the appropriate section of the web applications


example1.jpg

<cfcomponent name="Customer" output="false">
  <cfscript>
    this.name = "";
    this.address = "";
    this.customerType = 0;
    this.balanceDue = 0;
  </cfscript>
</cfcomponent>
<!--- 
  ideally all the attributes should be in variables scope and have a get/set method defined, 
  but i am skipping that portion, so that i can focus on strategy pattern, and to have 
  less code :-) 
--->

There came a request for business to also start storing the latitude and longitude of customer location in the database and it was decided that we are going to use Google’s reverse lookup service, everybody agreed and the core Customer.cfc got updated to
example2.jpg

<cfcomponent name="Customer" output="false">
  <cfscript>
    this.name = "";
    this.address = "";
    this.customerType = 0;
    this.balanceDue = 0;
    this.latitude = 0;
    this.longitude = 0;
  </cfscript>
  
  <cffunction name="reverseLookup">
    <!--- 
      perform the reverse geocode with google  and return the values back as a string
      and also update the latitude and logitude attribute
    --->
    <cfreturn "">
  </cffunction>
</cfcomponent>

Here you can see two new properties were added and a method was added to perform the reverse lookup.

This worked fine, until business came back and said that they are not pleased with Google’s service and want to use yahoo, the simpler solution would be just remove the Google specific code and replace it with yahoo code, but the architect decided why not have both in place, who know the business may change their mind, so the code updated to.

example3.jpg

<cfcomponent name="Customer" output="false">
  <cfscript>
    this.name = "";
    this.address = "";
    this.customerType = 0;
    this.balanceDue = 0;
    this.latitude = 0;
    this.longitude = 0;
  </cfscript>
  
  <cffunction name="reverseLookup">
    <cfargument name="serviceID" type="numeric" required="true">
    <cfif serviceID EQ 1>
      <!--- google code--->
    <cfelseif serviceID EQ 2>
      <!--- yahoo code--->
    </cfif>
    <cfreturn "">
  </cffunction>
</cfcomponent>

As you can see the core component introduced the notion of serviceID, where the developers or consumer of this component has to supply the service ID i.e. yahooID or googleID. The change was made but it involved much pain because all the developers has to be notified about it and also the other applications that were using the component had to made updates because the interface for the core component got changed.

Now after some time, the business came up with another suggestion they had found this database that can be bought which has all the required data to perform the reverse lookup without going to any third party and wanted the development team to implement it. To accommodate this request the core component had to be again updated, with an additional IF condition
<cfcomponent name="Customer" output="false">
  <cfscript>
    this.name = "";
    this.address = "";
    this.customerType = 0;
    this.balanceDue = 0;
    this.latitude = 0;
    this.longitude = 0;
  </cfscript>
  
  <cffunction name="reverseLookup">
    <cfargument name="serviceID" type="numeric" required="true">
    <cfif serviceID EQ 1>
      <!--- google code--->
    <cfelseif serviceID EQ 2>
      <!--- yahoo code--->
    <cfelseif serviceID EQ 3>
      <!--- db code--->
    </cfif>
    <cfreturn "">
  </cffunction>
</cfcomponent>

As you can see in every situation the core component gets effected, i.e. any time a new vendor is found the core component has to be updated with additional IF logic, which means the core component has to be touched every time and developed team really does not want to do that because of downside impact that may happened if a bug got introduced during the change.

How does Strategy Pattern Solves the above problem?

Strategy Pattern is the perfect solution for the above mentioned scenario, where first of the the calculation/algorithm (i.e. the reverse geocoding) part of the code, gets split into a component of its own, so there will be a .cfc file for each of the reverse geocoding i.e. googleReversGeocoding.cfc , yahooReversGeocoding.cfc and databaseReversGeocoding.cfc and they all will inherit a single interface to perform decoding

example4.jpg
example5.jpg
IReverseLookup.cfc

<cfinterface name="IReverseLookup">
  <cffunction name="decode" returntype="string">
    <cfargument name="address" type="String" required="true">
  </cffunction>
</cfinterface>

GoogleReverseLookup.cfc

<cfcomponent name="GoogleReverseLookup" implements="IReverseLookup">
  <cffunction name="decode" returntype="String">
    <cfargument name="address" type="String" required="true">
    <!--- 
      make calls to google 
      and return the data
    --->
    <cfreturn "1929202.111, 292920.211">
  </cffunction>
</cfcomponent>

YahooReverseLookup.cfc

<cfcomponent name="YahooReverseLookup" implements="IReverseLookup">
  <cffunction name="decode" returntype="String">
    <cfargument name="address" type="String" required="true">
    <!--- 
      make calls to yahoo
      and return the data
    --->
    <cfreturn "0119182781.111, 5111192929.211">
  </cffunction>
</cfcomponent>

DatabaseReverseLookup.cfc

<cfcomponent name="DatabaseReverseLookup" implements="IReverseLookup">
  <cffunction name="decode" returntype="String">
    <cfargument name="address" type="String" required="true">
    <!--- 
      make calls to Database
      and return the data
    --->
    <cfreturn "000002221, 0028289.857">
  </cffunction>
</cfcomponent>

DatabaseReverseLookup.cfc

<cfcomponent name="Customer" output="false">
  <cfscript>
    this.name = "";
    this.address = "";
    this.customerType = 0;
    this.balanceDue = 0;
    this.latitude = 0;
    this.longitude = 0;
  </cfscript>
  
  <cffunction name="reverseLookup">
    <cfargument name="reversLookupStrategy" type="IReverseLookup" required="true">
    <cfreturn reversLookupStrategy.decode(this.address)>
  </cffunction>
</cfcomponent>

example1.cfm

<cfset customer = CreateObject("component", "Customer")>
<cfset customer.address = "410 washington Street, Greely, NC 10001">
<!--- set other properties --->

<!--- code wasts to use google service --->
<cfset strategy = CreateObject("component", "GoogleReverseLookup")>
<cfoutput>#customer.reverseLookup(strategy)#<br></cfoutput>

<!--- code wasts to use yahoo service --->
<cfset strategy = CreateObject("component", "YahooReverseLookup")>
<cfoutput>#customer.reverseLookup(strategy)#<br></cfoutput>

<!--- code wasts to use database service --->
<cfset strategy = CreateObject("component", "DatabaseReverseLookup")>
<cfoutput>#customer.reverseLookup(strategy)#<br></cfoutput>

So with the strategy pattern, now we will have cleaner implementation, where decoding with each vendor/service is done separately and Customer class (cfc) does not care about what vendor we are using as long the object that is being passed to it implements the IReverseLookup interface then that’s all it cares about. With this type of implementation you can add as my vendor and defined the logic in separate CFC (implement the interface) and you will never have to be updated the customer object. This way the code that is using this component can at runtime decide what strategy i.e. calculation to use without effecting the core component.

When can you use the strategy pattern be used?

a) If you have multiple components (CFC) that have structural similarity , but have different behavior (due diligence has to be done)
b) You have algorithm whose calculation can vary depending up the parameters passed to it.
c) Have excessive use of switch or if statement, and you have a desire to clear it up ?
d) You don’t want your core component to updated every time a new strategy is developed or requested.

Download Source Code

2 comments June 28th, 2008

Prototype Pattern in ColdFusion 8

The prototype means making a clone. This implies cloning of an object to avoid creation. If the cost of creating a new object is large and creation is resource intensive, we clone the object. This article explains how this pattern can be used in coldfusion

I set out tonight to determine if the Prototype design pattern would be useful in object factories in ColdFusion 8. The Prototype pattern, in a nutshell, is to create a new instance of an object by copying an existing object instantiation. The object to copy is an object instantiated once and then used as a blueprint for future objects of the same type. The thought is that copying an object holds a lesser cost than instantiating a new object.

Read the full Article

Add comment December 26th, 2007

DAOs and Gateways in ColdFusion

Brief introduction of DAO and Gateway pattern for coldfusion audience

Data Access Object and Gateways are the names given to ColdFusion components that access information from a database or other external data source. Within the ColdFusion community DAOs and Gateways have pretty much taken on the meaning as follows

Read the full Article

Add comment December 22nd, 2007

Object Factory in Coldfusion

Factory method pattern implementation in coldfusion along with working sample code, This pattern helps to model an interface for creating an object which at creation time can let its subclasses decide which class to instantiate.

For those of you new to this concept, an object factory is nothing but a component whose sole job is to create components. An object factory is quite simple and small. Its main role is to collect the information necessary to create an instance of the intended object’s class and then to invoke that class’s constructor

Read the full Article

Add comment December 16th, 2007

Command Pattern in Coldfusion

Object in command pattern are used to represent action and can be used effectively in coldfusion, this Article explains the command pattern by building a demo application.

The tutorial is simple in its presentation but gets the job done and includes a full working application putting everything to good use. You’ll be creating a home automation Remote Control for the appliances in your house. My remote has simple on/off buttons and and undo button but the tutorial will teach you to do more

Read the full Article

Add comment December 10th, 2007

Implement the State pattern with ColdFusion Components

State Pattern implementation in coldfusion to maintain the various state of an object. The article provides step by step implementation along with downloadable code for future reference.

The introduction of ColdFusion Components (CFCs) in ColdFusion MX opened the door to more object-oriented programming in CF. When application developers start thinking about OOP, the idea of design patterns almost always comes up. In that context, Brian Kotek discusses the State pattern: its purpose, the problems it can solve, and how you can implement it using CFCs.

http://articles.techrepublic.com.com/5100-3513_11-6167539.html

Add comment December 4th, 2007

Singleton Pattern in Coldfusion

Coldfusion implementation of singleton pattern to restrict instantiation of class to one object. Singleton Pattern is useful when exactly one object is needed to coordinate actions across the system. Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist

Singletons are perhaps one of the most simple Design Patterns. For those who don’t know sigletons are a class that can only have one instance. They can be thought of as a glorified global variable - but are a lot more useful.

Read the full Article

Add comment November 27th, 2007

Strategy pattern Example for Coldfusion

Demo application with source code showing the usage of strategy pattern to dynamically select/change the class behavior at runtime and without having to lock the class to a specific behavior

As I make my way through Head First Design Patterns, which I am starting to agree is a “must” on a developer’s bookshelf, I decided I would work out some of the exercises in ColdFusion code. It is geared towards Java, but the principles carry over into OOP practices in ColdFusion as well.

Read the full Article

Add comment November 23rd, 2007

Using Composite pattern in Coldfusion

Brendan O’Hare has written an excellent article explaining the Composite Design Pattern and its implementation in ColdFusion by using CFC (ColdFusion Components)

“As ColdFusion developers, we tend to build applications based on pages that display information and queries to retrieve information and save information. We tend to think solely of how we are going to implement the code required to perform a certain function. Many times we are not able to consider the commonality of a certain problem and whether an already established design exists somewhere.

Often we are not able to set aside time to do this research. Knowing and utilizing design patterns allows us to think in a common language, with an ever-expanding library of well thought out solutions to consider when architecting an application. Recognition of these patterns in our everyday jobs can make us significantly more productive and seem even smarter than we are.”

Read the Full Article

Add comment November 19th, 2007


 Subscribe in a RSS reader


CourseLookup.us - Providing course and conference information to enhance your knowledge base.

Tags

Calendar

March 2010
M T W T F S S
« Dec    
1234567
891011121314
15161718192021
22232425262728
293031  

Posts by Month

Posts by Category