Monday 12 April 2010

ColdFusion Head First Design Patterns: Decorator

Continuing in this design patterns series taken from Head First Design Patterns, is a ColdFusion implementation of the Decorator Pattern.

Abstract Beverage

Beverage.cfc

<cfcomponent output="false">

  <cfset VARIABLES.description = "Unknown Beverage">
  
  <cffunction access="public" returntype="string" name="getDescription">
    <cfreturn VARIABLES.description>
  </cffunction>

  <cffunction access="public" returntype="numeric" name="cost" >    
  </cffunction>

</cfcomponent>

Abstract Decorator

CondimentDecorator.cfc

<cfcomponent extends="Beverage" output="false">
  
  <cffunction access="public" returntype="string" name="getDescription">
  </cffunction>
  
</cfcomponent>

Concrete Beverages

HouseBlend.cfc

<cfcomponent extends="Beverage" output="false">

  <cffunction access="public" name="init" returntype="HouseBlend">
    <cfset VARIABLES.description = "House Blend Coffee">
    
    <cfreturn THIS>
  </cffunction>  

  <cffunction access="public" returntype="numeric" name="cost" >
    <cfreturn 0.89>    
  </cffunction>  

</cfcomponent>

Espresso.cfc

<cfcomponent extends="Beverage">

  <cffunction access="public" name="init" returntype="Espresso">
    <cfset VARIABLES.description = "Espresso">
    
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="numeric" name="cost" >
    <cfreturn 1.99>    
  </cffunction>
  
</cfcomponent>

Concrete Decorators

Mocha.cfc

<cfcomponent extends="CondimentDecorator">

  <cffunction access="public" name="init" returntype="Mocha">
    <cfargument type="Beverage" name="beverage">
    
    <cfset VARIABLES.beverage = ARGUMENTS.beverage>
    
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="string" name="getDescription">
    <cfreturn VARIABLES.beverage.getDescription() & ", Mocha">
  </cffunction>

  <cffunction access="public" returntype="numeric" name="cost" >
    <cfreturn 0.20 + VARIABLES.beverage.cost()>
  </cffunction>

</cfcomponent>

Test Page

StarbuzzCoffee.cfm

<cfset beverage = createObject("component", "Espresso").init()>

<cfset beverage2 = createObject("component", "HouseBlend").init()>
<cfset beverage2 = createObject("component", "Mocha").init(beverage2)>
<cfset beverage2 = createObject("component", "Mocha").init(beverage2)>

<cfoutput>
  #beverage.getDescription()# $#beverage.cost()#
  <br />
  #beverage2.getDescription()# $#beverage2.cost()#
</cfoutput>

Source Code