Although it wasn’t always the case, these days a good understanding of object oriented programming principles and the use of common design patterns are essential in order to become a successful Actionscript developer. When we’re working on projects, the Head First Design Patterns book is never far away – and one of the patterns that has been incredibly useful time and time again is the Abstract Factory and variations thereof, so I thought we’d dedicate a YouTube tutorial to it.

I’d love to hear about your own experiences in regards to object oriented programming in AS3 – please leave a comment!

The material in this blog post and in the video is an excerpt from our Advanced Actionscript 3 (Object Oriented Programming and Design Patterns) training course.

You can watch the video and read up on the details after the break.

Making Choices

The Abstract Factory Design Pattern is all about choice. Not any kind of choice mind you – but very specifically choosing which class to instantiate given certain conditions. Whether you realise it or not, you are probably making these choices numerous times in your own programming code. Here are some examples:

  • Which type of menu to display based on the admin privileges of the current user
  • Which type of skin to apply to your game characters, based on the selections made at the beginning of the game – and subsequently which types of weapons are available for that character
  • Which type of button graphic to use based on the size of a banner
  • Which type of XML parser to use based on the type of feed the user has loaded in

and so on. Once you’re dealing with object oriented programming, most of those choices are going to result in a class being instantiated and the trick is to choose the correct class based on a set of circumstances.

No problem, right? You just whack an if-statement in there:

if( user.isAdmin ){
    menu = new AdminMenu();
}else{
    menu = new NormalMenu();
}

Weeds Everywhere

Of course, using if-statements will work fine, however it spreads the choices throughout your application, like a weed taking a strong-hold in your garden, then your front lawn, then your walls…you get the picture. Suppose you introduce a third user privilege level? Time to revisit all those many if-statements (of course you’ll remember where they are!). The more complex your project, the more difficult, time-consuming and error prone such a change becomes.

Factory Pattern to the Rescue

It is in these cases that the Factory Design Pattern comes to your rescue, by moving the choice into a single, isolated piece of code. The resulting class that is instantiated – the factory – will then provide the application with the correct class instances. As a result, you only need to change the single point-of-choice and create a new factory class in order to make wide-ranging changes to your entire application.

In practice, it looks something like this:

// isolated choice code (eg. after user logs in)
if( user.isAdmin )
{
    factory = new AdminUserFactory();
}else{
    factory = new NormalUserFactory();
}
 
// and in the AdminUserFactory class:
function getMenu():Menu
{
    return new AdminMenu();
}
 
// and in the NormalUserFactory class:
function getMenu():Menu
{
    return new NormalMenu();
}
 
// much later, in a remote location in your code-tree
menu = factory.getMenu();

Can you see how you would add a third user level – and how much more manageable it has become compared to the previous example?

Let’s follow the example code through to its logical conclusion. Say we have 10 user levels. Then we’ll end up with 10 different factory classes (AdminUserFactory, NormalUserFactory, SuperUserFactory, etc). So far so good. But how does the code that is actually using the factory to retrieve the menu know how to deal with all those 10 different classes without using another if-statement? Surely that will lead to type-errors if we don’t know the exact data-type?

Interfacing with the Factory

In order to allow code throughout your application to use different factory classes, we’re going to use an interface to define what methods a factory class provides. This interface will be used as the data-type when passing the factory around to other pieces of code. So in practice it doesn’t matter which factory class is used behind the scenes and dependencies within your code are reduced to a single interface class, which is what we like to see!

Our user-menu example seems to use factory to create its user-interface elements, so let’s create an interface called IUIFactory. We start with just a single function – we can always add to it later on:

// in the IUIFactory.as file
public interface IUIFactory {
    function getMenu():Menu;
}

As a rule, you’d start with your interface first, then create your first factory class and then create your choice code – otherwise you’ll end up in a bit of a pickle.

Here is the sample code from earlier, with the interface thrown in.

// we start with an interface
var factory:IUIFactory;
if( user.isAdmin )
{
    factory = new AdminUserFactory();
}else{
    factory = new NormalUserFactory();
}
 
// and in the AdminUserFactory class - which implements IUIFactory
public function getMenu():Menu
{
    return new AdminMenu();
}
 
// and in the NormalUserFactory class - which also implements IUIFactory
public function getMenu():Menu
{
    return new NormalMenu();
}
 
// much later, in a remote location in your code-tree
var factory:IUIFactory;
menu = factory.getMenu();

Splendid.

Another beneficial side-effect of using an interface in this way comes into play when adding new features to your factory. Any new feature requires a new method in your factory interface. That new method will immediately result in compiler errors because none of your factory classes has implemented it yet. You have no option but to implement the new method in every single factory class – hence automatically making sure that your code is properly maintained.

Doesn’t that sound better than finding a long-lost if-statement deep down in the murky depths of your code-tree that your colleague forgot to change when they added a new user-group?

YouTube Tutorial and Source Code

The YouTube tutorial steps through a different example of coding a user-interface that can change depending on the age-group of the viewer.

You can download the source-code as a FlashBuilder 4 project so that you can follow the tutorial and experiment further. There are a couple of extra images in the assets folder so you can produce a third factory class. Copyright / licensing info is included in each file, all images used are publicly available via sxc.hu.

Further Thoughts – Factory Pattern and Dependency Injection

The Factory Design Pattern’s strengths come from isolating choices in a single location. Furthermore, each factory class also encapsulates a very simple set of actions – it knows how to create the correct instances but doesn’t require knowledge of the surrounding application to do so – so we are adhering to the  ’one class – one responsibility’ concept.

Of course you still need to pass the actual factory instance around to the classes that require them and there are various ways of managing these dependencies. In the YouTube tutorial, I simply pass the factory instance to the view classes via their constructor and this is a perfectly valid way of handling it.

There are of course other options – and Dependency Injection (DI) is especially helpful when working with the factory pattern.

Since DI hinges in principal around matching interface data-types to concrete classes, switching factory classes becomes a doddle. You simply specify the appropriate factory class to be used when the DI container encounters the factory interface and your project can be dramatically changed by essentially touching only a single line of code. This is especially true when there is a fixed, pre-determined choice of factory class, for example when repurposing an entire project for a different market or target audience.

I’d love to hear your own experiences of the Factory Pattern and OOP in general – leave a note in the comments below.