Abstract Factory Pattern

  Home

Description

This could be described roughly as a factory that produces factories. The usual description is a factory that produces toolkits.

Example

So what does that mean? Well, here's an example: we are consulting an entertainment company that produces movies and TV shows. Some of the classes involved would be Customer, Product, Deal, License, Market, SalesPerson. Now products can be licensed in different media such as Pay-Per-View, Premium Cable, Basic Cable, Domestic TV, International TV, etc. and the deals are very different in each media. The classes we described earlier vary across these media. For example, an international TV deal involves different languages (e.g., French, German and Italian) and many markets (e.g., France, Switzerland, Belgium, Germany, Italy), whereas a domestic TV deal involves only one language (e.g., Spanish) and one market (e.g., Los Angeles). Also the way the customers are viewed within the different media is different and the data associated with a customer is different. The sales people are paid differently and different data about them is kept in each media. So we have a set of class heirarchies something like this:

                     Customer
                        |
   -----------------------------------------------
   |                    |                |        |
DomesticTVCustomer  IntTVCustomer  PPVCustomer   etc
 
 
                       Deal
                        |
  --------------------------------------------
  |                     |           |        |
DomesticTVDeal      IntTVDeal     PPVDeal   etc
The code might look something like this:

Public MustInherit Class Deal
    Public MustOverride Sub MakeLotsOfMoney()
    'other members of deal
End Class
 
Public Class DomesticTVDeal : Inherits Deal
    Public Overrides Sub MakeLotsOfMoney()
        'Money making code goes here
    End Sub
    'etc ...
End Class
 
Public Class PPVDeal : Inherits Deal
    Public Overrides Sub MakeLotsOfMoney()
        'Money making code goes here
    End Sub
    'etc ...
End Class
And there are several other similar heirarchies for the other classes. Now we don't want to have to write different code for every media so how can we get around it? Well, what if we create a factory that creates the objects for the different media?

Public Class MediaFactory
    Public Function GetCustomer(media As MediaType) as Customer
        Select Case media
            Case MediaType.DOMESTIC
                return New DomesticTVCustomer
            Case MediaType.INTERNATIONAL
                return New InternationalCustomer
            Case MediaType.PPV
                return New PPVCustomer
            Case ETC
                'etc ...
        End Select
    End Function
 
    Public Functon GetDeal(media As Integer) as Deal
        'big select statement
    End Function
 
    Public Function GetLicense(media As Integer) as License
        'big select statement
    End Function
 
    'etc ...
End Class
Not bad but now we have big select statements in every method and if we add a new media we have to go into every method and add something to the select. Well, what if we make a factory that generates factories, one for each media? The resulting "factory" classes are not really factories so they often get called "toolkits". But remember that for the Factory pattern we have to create a super-class for the toolkits and then a factory class to create the toolkit objects. So let's kill two birds with one stone and put the Factory method into the super-class. Now we have something like this:

Public MustInherit Class AbstractMediaFactory
 
    Public Enum MediaType As Integer
        DOMESTIC
        INTERNATIONAL
        PPV
        'etc ...
    End Enum
 
    Public Shared Function GetFactory(media As MediaType) As AbstractMediaFactory
        Select Case media
            Case MediaType.DOMESTIC
                Return New DomesticTVFactory
 
            Case MediaType.INTERNATIONAL
                Return New InternationalTVFactory
 
            Case MediaType.PPV
                Return New PPVFactory
 
            Case MediaType.ETC
                'etc ...
 
            Case Else
                Return Nothing
 
        End Select
    End Function
 
    Public MustOverride Function GetDeal() As Deal
    Public MustOverride Function GetCustomer() As Customer
    Public MustOverride Function GetLicense() As License
    'Other GetXXX functions go here
End Class
 
Public Class DomesticTVFactory : Inherits AbstractMediaFactory
    Public Overrides Function GetDeal() As Deal
        Return New DomesticTVDeal
    End Function
 
    Public Overrides Function GetCustomer() As Customer
        Return New DomesticTVCustomer
    End Function
 
    Public Overrides Function GetLicense() As License
        Return New DomesticTVLicense
    End Function
End Class
 
Public Class PPVFactory : Inherits AbstractMediaFactory
    Public Overrides Function GetDeal() As Deal
        Return New PPVDeal
    End Function
 
    Public Overrides Function GetCustomer() As Customer
        Return New PPVCustomer
    End Function
 
    Public Overrides Function GetLicense() As License
        Return New PPVLicense
    End Function
End Class
To use this pattern we first get the factory (or toolkit) we need

Dim myFactory as AbstractMediaFactory
myFactory = AbstractMediaFactory.GetFactory(media)
Then we get the specific object we want to use:

Dim theDeal as Deal
theDeal = myFactory.GetDeal()
theDeal.MakeLotsOfMoney()
Now if we want to add a new media we simply create the classes and toolkit class for the media, then add a "Case MediaType.NEWMEDIA" to the Select statement in the abstract factory class.
Resources

Data & Object Factory - Design Patterns: Abstract Factory

Wikipedia - Abstract factory pattern

DotNetExtreme - Abstract Factory Pattern

1