Design Patterns: Mastering Template Method in Swift

Design Patterns: Mastering Template Method in Swift

Design patterns are an important part of software engineering. They provide us with a way to structure our code and make it more maintainable and reusable. One of the most commonly used design patterns is the Template Method. In this blog post, we’ll take a look at how to use the Template Method pattern in Swift.

The Template Method pattern is based on the idea of using a template or “skeleton” to define the steps of an algorithm. The details of each step are then left up to the subclasses to implement. This allows us to separate the high-level structure of the algorithm from the details of each individual step.

In Swift, the Template Method pattern is implemented by defining a base class with an abstract method (or methods) that represent the steps of the algorithm. The subclasses then override these methods and provide their own implementations.

Let’s take a look at an example. We’ll create a simple game that has two players (PlayerA and PlayerB). Each player has a score that is incremented when they win a round. The game is played in rounds until one of the players reaches a certain number of points (in this example, 5 points).

First, we’ll define our base class. This will contain the template method that defines the structure of the algorithm. We’ll call this class GameManager:

class GameManager {
    func play() {
        startGame()
        while !gameOver() {
            playRound()
        }
        endGame()
    }
    
    func startGame() {
        // To be overriden by subclasses
    }
    
    func playRound() {
        // To be overriden by subclasses
    }
    
    func gameOver() -> Bool {
        // To be overriden by subclasses
        return false
    }
    
    func endGame() {
        // To be overriden by subclasses
    }
}

As you can see, the GameManager class contains four methods: startGame(), playRound(), gameOver(), and endGame(). These methods represent the steps of the algorithm and will be overridden by the subclasses.

Next, we’ll create two subclasses of GameManager: PlayerA and PlayerB. These classes will provide the implementation of the template methods. Let’s take a look at PlayerA’s implementation:

class PlayerA: GameManager {
    var score = 0
    
    override func startGame() {
        print("Player A starts the game")
    }
    
    override func playRound() {
        let randomNumber = Int.random(in: 0..<2)
        if randomNumber == 0 {
            score += 1
            print("Player A won the round")
        } else {
            print("Player A lost the round")
        }
    }
    
    override func gameOver() -> Bool {
        return score >= 5
    }
    
    override func endGame() {
        print("Player A won the game!")
    }
}

We can see that the PlayerA class overrides the four template methods. The startGame() method simply prints out a message to indicate that the game has started. The playRound() method generates a random number and increments the score if it is 0. The gameOver() method returns true when the score is 5 or more. Finally, the endGame() method prints out a message to indicate that the game has ended.

Finally, we’ll create a PlayerB class that is similar to PlayerA. This class will also override the template methods:

class PlayerB: GameManager {
    var score = 0
    
    override func startGame() {
        print("Player B starts the game")
    }
    
    override func playRound() {
        let randomNumber = Int.random(in: 0..<2)
        if randomNumber == 1 {
            score += 1
            print("Player B won the round")
        } else {
            print("Player B lost the round")
        }
    }
    
    override func gameOver() -> Bool {
        return score >= 5
    }
    
    override func endGame() {
        print("Player B won the game!")
    }
}

Now that we have our classes set up, we can create instances of them and call the play() method to run the game:

let playerA = PlayerA()
let playerB = PlayerB()

playerA.play()
playerB.play()

When we run this code, we should see the players playing rounds until one of them reaches 5 points. Then, the game will end and the winning player will be announced.

In this blog post, we’ve seen how to use the Template Method pattern in Swift. We created a base class with an abstract method that defined the steps of the algorithm. We then created subclasses that provided the implementation of each step. This allowed us to separate the high-level structure of the algorithm from the details of each individual step.

The Template Method pattern is a powerful tool for structuring code and making it more maintainable and reusable. It is an important part of software engineering and should be used whenever possible.

Scroll to Top