# Abstract Factory Pattern

version 2.4.21

The Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme. It embodies the intent of a normal factory, i.e. remove the need for code using an interface to know the concrete implementation behind the interface, but applies to a set of interfaces and selects an entire family of concrete classes which implement those interfaces.

As an example, I might have interfaces Button, TextField and Scrollbar. I might have WindowsButton, MacButton, FlashButton as concrete classes for Button. I might have WindowsScrollBar, MacScrollBar and FlashScrollBar as concrete implementations for ScrollBar. Using the Abstract Factory Pattern should allow me to select which windowing system (i.e. Windows, Mac, Flash) I want to use once and from then on should be able to write code that references the interfaces but is always using the appropriate concrete classes (all from the one windowing system) under the covers.

## 1. Example

Suppose we want to write a game system. We might note that many games have very similar features and control.

We decide to try to split the common and game-specific code into separate classes.

First let’s look at the game-specific code for a Two-up game:

    class TwoupMessages {
        def welcome = 'Welcome to the twoup game, you start with $1000'
        def done = 'Sorry, you have no money left, goodbye'
    }

    class TwoupInputConverter {
        def convert(input) { input.toInteger() }
    }

    class TwoupControl {
        private money = 1000
        private random = new Random()
        private tossWasHead() {
            def next = random.nextInt()
            return next % 2 == 0
        }
        def moreTurns() {
            if (money > 0) {
                println "You have $money, how much would you like to bet?"
                return true
            }

            false
        }
        def play(amount) {
            def coin1 = tossWasHead()
            def coin2 = tossWasHead()
            if (coin1 && coin2) {
                money += amount
                println 'You win'
            } else if (!coin1 && !coin2) {
                money -= amount
                println 'You lose'
            } else {
                println 'Draw'
            }
        }
    }

Now, let’s look at the game-specific code for a number guessing game:

    class GuessGameMessages {
        def welcome = 'Welcome to the guessing game, my secret number is between 1 and 100'
        def done = 'Correct'
    }

    class GuessGameInputConverter {
        def convert(input) { input.toInteger() }
    }

    class GuessGameControl {
        private lower = 1
        private upper = 100
        private guess = new Random().nextInt(upper - lower) + lower
        def moreTurns() {
            def done = (lower == guess || upper == guess)
            if (!done) {
                println "Enter a number between $lower and $upper"
            }

            !done
        }
        def play(nextGuess) {
            if (nextGuess <= guess) {
                lower = [lower, nextGuess].max()
            }
            if (nextGuess >= guess) {
                upper = [upper, nextGuess].min()
            }
        }
    }

Now, let’s write our factory code:

    def guessFactory = [messages: GuessGameMessages, control: GuessGameControl, converter: GuessGameInputConverter]
    def twoupFactory = [messages: TwoupMessages, control: TwoupControl, converter: TwoupInputConverter]

    class GameFactory {
        def static factory
        def static getMessages() { return factory.messages.newInstance() }
        def static getControl() { return factory.control.newInstance() }
        def static getConverter() { return factory.converter.newInstance() }
    }

The important aspect of this factory is that it allows selection of an entire family of concrete classes.

Here is how we would use the factory:

    GameFactory.factory = twoupFactory
    def messages = GameFactory.messages
    def control = GameFactory.control
    def converter = GameFactory.converter
    println messages.welcome
    def reader = new BufferedReader(new InputStreamReader(System.in))
    while (control.moreTurns()) {
        def input = reader.readLine().trim()
        control.play(converter.convert(input))
    }
    println messages.done

Note that the first line configures which family of concrete game classes we will use. It’s not important that we selected which family to use by using the factory property as shown in the first line. Other ways would be equally valid examples of this pattern. For example, we may have asked the user which game they wanted to play or determined which game from an environment setting.

With the code as shown, the game might look like this when run:

    Welcome to the twoup game, you start with $1000
    You have 1000, how much would you like to bet?
    300
    Draw
    You have 1000, how much would you like to bet?
    700
    You win
    You have 1700, how much would you like to bet?
    1700
    You lose
    Sorry, you have no money left, goodbye

If we change the first line of the script to GameFactory.factory = guessFactory, then the sample run might look like this:

    Welcome to the guessing game, my secret number is between 1 and 100
    Enter a number between 1 and 100
    75
    Enter a number between 1 and 75
    35
    Enter a number between 1 and 35
    15
    Enter a number between 1 and 15
    5
    Enter a number between 5 and 15
    10
    Correct