Design patterns – Part 4: Factory method pattern
Factory method pattern definition:
The Factory method pattern defines an interface for creating and objects, but lets subclasses to decide which class they will create.
Huh?
I will try to present this pattern on a simple example. Imagine you work in a company that sales software. However, this software is, due to different laws, different for each country/region it is sold in (in our case EU and USA). You have two types of software (Pro and Basic that differ by price and package). You will need to create a single store that will allow users to only buy products from their country.
First, you can create an abstract class that will represent a product.
Class CSoftware m_strName As String Property Get ProductName As String ProductName = Me.m_strName End Property Sub New End Sub Sub PreparePackage () End Sub Sub PrintPrice () End Sub End Class
As you can see, the class itself is pretty simple. It contains a member variable for product name and has two methods that will prepare a package and print it’s price.
Now (as you need two product types for two countries) you need to create 4 product classes that will inherit from CSoftware class. I will only show you both EU classes as others are pretty self explanatory.
Class CEUSoftwareBasic As CSoftware Sub New Me.m_strName = "EU Basic" End Sub Sub PreparePackage () 'TODO: put your code here End Sub Sub PrintPrice () 'TODO: put your code here End Sub End Class Class CEUSoftwarePro As CSoftware Sub New Me.m_strName = "EU Pro" End Sub Sub PreparePackage () 'TODO: put your code here End Sub Sub PrintPrice () 'TODO: put your code here End Sub End Class
There. You are done with products. Now, you need two stores, that will create desired products. But first, you should create an abstract store class.
Class CSoftwareStore Function orderSoftware (swtype As String) As CSoftware Dim sw As CSoftware Set sw = createSoftwarePackage (swtype) Call sw.PreparePackage () Call sw.PrintPrice () Set orderSoftware = sw End Function Function createSoftwarePackage (swtype As String) As CSoftware End Function End Class
As you can see, createSoftwarePackage method is empty. This is because createSoftwarePackage differs from store to store. Method orderSoftware, though, is the same for all stores and can be implemented in abstract class.
Now, a source of both stores that inherit from CSoftwareStore.
Class CEUSoftwareStore As CSoftwareStore Function createSoftwarePackage (swtype As String) As CSoftware Dim sw As CSoftware Select Case (Lcase (swtype)) Case "basic": Set sw = New CEUSoftwareBasic () Case "pro": Set sw = New CEUSoftwarePro () End Select Set createSoftwarePackage = sw End Function End Class Class CUSASoftwareStore As CSoftwareStore Function createSoftwarePackage (swtype As String) As CSoftware Dim sw As CSoftware Select Case (Lcase (swtype)) Case "basic": Set sw = New CUSASoftwareBasic () Case "pro": Set sw = New CUSASoftwarePro () End Select Set createSoftwarePackage = sw End Function End Class
Each store creates and returns an object depending on the type we wanted.
But what will that bring me?
You will only have to know which store you need to use and not care about the product returned. That is a job of each separate store. Thus, your code will be easier to read and to maintain.
Pasted below is a sample execution code.
Sub Initialize Dim storeEU As CEUSoftwareStore Dim storeUSA As CUSASoftwareStore Dim sw As CSoftware Set storeEU = New CEUSoftwareStore () Set storeUSA = New CUSASoftwareStore () Set sw = storeEU.orderSoftware ("basic") Print "Package: " & sw.ProductName Set sw = storeUSA.orderSoftware ("pro") Print "Package: " & sw.ProductName End Sub
The agent creates both stores and then for each store orders a software. Printed results should be:
Package: EU Basic Package: USA Pro
August 24th, 2011 at 12:51
Thanks for the code, but I have only one thing: You are not applying the factory design pattern on the STORE classes – only the SOFTWARE class and that is a bit confusing and need to be addressed/mentioned in the text. Actually, I would apply the factory design pattern even on the STORE classes:
Public Function getStore(country As String) As CSoftwareStore
Select Case country
Case “USA”
Set getStore = New CUSASoftwareStore
Case Else
Set getStore = New CEUSoftwareStore
End Select
End Function
and then in the agent I could replace the “Dim storeEU” and “Dim storeUSA” with
Dim store As CSoftwareStore
Set store = getStore(“USA”)
Set sw = store.orderSoftware(“basic”)
or
Set store = getStore(“EU”)
Set sw = store.orderSoftware(“pro”)
With this approach, the implementation of the different stores are hidden which is one of the main reasons for using the factory design pattern.