Home Programming Swift 2 Design Patterns

Swift 2 Design Patterns

By Julien Lange
books-svg-icon Book
eBook $21.99 $14.99
Print $26.99 $15.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $21.99 $14.99
Print $26.99 $15.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Creational Patterns
About this book
Publication date:
October 2015
Publisher
Packt
Pages
224
ISBN
9781785887611

 

Chapter 1. Creational Patterns

The creational patterns are designed to deal with the object creation mechanism in software designing. A system using these patterns becomes independent of how objects are created, which means it is independent of how concrete classes are instantiated.

These patterns encapsulate the use of concrete classes and favor the use of interfaces in the relationship between objects, allowing to have better abstraction of the global system conception.

Thus, if we analyze the singleton pattern, a pattern designed to instantiate only one instance of a class, we find that the mechanism that controls the unique access to this instance is fully encapsulated in the class, which means that this is completely transparent to the client consuming the instance of the class.

In this chapter, we will introduce you to the five creational patterns and discuss how we can use them with Swift:

  • The prototype pattern

  • The factory method pattern

  • The singleton pattern

  • The abstract factory pattern

  • The builder pattern

The objectives of these patterns are described in the following table:

Pattern

Objective

The prototype pattern

This pattern allows you to create new objects by duplicating existing objects called prototypes. This pattern has the cloning capability.

The factory method pattern

This pattern introduces you to an abstract method that allows you to create an object by telling its subclasses about the effective creation of the object.

The singleton pattern

This pattern ensures that a class has only one instance. This class provides a unique point of access that returns this instance.

The abstract factory pattern

This pattern allows you to create an object that is grouped in families by hiding the concrete classes that are needed to create these objects.

The builder pattern

This pattern allows you to separate the creation of complex objects from their implementation. This permits a client to create complex objects having different representations.

 

The prototype pattern


Our first pattern will be the prototype pattern; we will see how we can use it to accelerate the creation of an instance. We will see how we can use it to copy an existing instance, and eventually, we will see how to modify the new one to our needs.

Roles

The prototype pattern is used to create a new object by duplicating existing objects called prototypes, and they have a cloning capability.

This pattern is used in the following use cases:

  • When you need to create an instance without knowing the hierarchy of a class

  • When you need to create class instances that are dynamically loaded

  • When you need to have a simple object system and not include a parallel hierarchy of a factory class

Design

The following diagram shows the generic class of the prototype pattern:

Participants

Participant to this pattern are as follows:

  • Client: This class contains a list of objects called prototypes that are instances of the AbstractPrototype abstract class. The Client class needs to clone these prototypes without having to know their internal structure and subclass hierarchy.

  • AbstractPrototype: This is an abstract class that can duplicate itself. This class contains a cloning method called clone().

  • ConcretePrototype1 and ConcretePrototype2: These are concrete classes that inherit from the AbstractPrototype class. They define a prototype and have both a cloning method called clone().

Collaborations

The client asks to one or more prototypes to clone themselves.

Illustration

A simple and real example of where this pattern can be applied is the famous game HeartStone from Blizzard (the creator of World of Warcraft). In this strategy card game, when you spend "mana" to use spells, weapons, or put a minion on the board, there is a special minion that has the ability to clone a particular card. When a player uses this card, it selects the minion that he or she wants to clone and the card becomes an exact copy of the selected card. The following card represent the "HeartStone" card that have this behavior:

Implementation

The following code represent the implementation of the pattern using Swift:

import UIKit

class AbstractCard {
  var name: String?
  var mana: Int?
  var attack: Int?
  var defense: Int?
  
  init(name:String?, mana:Int?, attack:Int?, defense:Int?) {
    self.name = name
    self.attack = attack
    self.defense = defense
    self.mana = mana
  }
  
  func clone() -> AbstractCard {
    return AbstractCard(name: self.name, mana: self.mana, attack: self.attack, defense: self.defense)
  }
}

class Card: AbstractCard {
  
  override init(name:String?, mana:Int?, attack:Int?, defense:Int? ) {
    super.init(name: name,mana: mana,attack: attack,defense: defense)

  }
}

Note

The AbstractPrototype class is our AbstractCard class, where we implement a way to return a copy of itself using the clone() method.

Usage

The following code simulate how the client will interact with the Card object which implement the prototype pattern:

// Simulate our client

// This is the card that we will copy
let raidLeader = Card(name: "Raid Leader", mana: 3, attack: 2, defense: 2)

// Now we use our faceless Manipulator card to clone the raidleader
let facelessManipulator = raidLeader.clone()

print("\(facelessManipulator.name, facelessManipulator.mana, facelessManipulator.attack, facelessManipulator.defense)")

Since the code is written in a Playground file, you should consider it as the code that you'll put in the Client class.

First, we instantiate a new card named Raid Leader. This is a concrete prototype class. Let say that you have the "Faceless Manipulator" card and you want to use it to clone the "Raid Leader" card, then you simply need to use the raidLeader.clone() method that will return a new instance with the exact same properties as "Raid Leader".

By checking the details on the right-hand side of the Playground file, you'll see that the facelessManipulator constant has exactly the same properties as raidLeader (line 39), as shown in the following screenshot:

 

The factory method pattern


Our second pattern is a very well-known pattern. It introduces you to the famous concept: "Program to an interface, not an implementation." The instantiation is done in the factory class that depends on the type that we need and the type that needs to be returned to the client.

Roles

The factory method pattern is one of the most used patterns in software designs. The purpose of this pattern is to abstract the creation of an object. The factory method lets a class defer instantiation to subclasses.

You'll see from that time to time that we have mentioned "program to an interface." This is exactly what this pattern does. With Swift, instead of an interface, you'll code with the "protocol" instead of the class itself.

This pattern is used in the following use cases:

  • A class only knows about abstract classes or interfaces of objects with whom it has some relationships

  • A class wants its subclasses to instantiate the object in order to benefit of polymorphism mechanism

Design

The following diagram shows the generic class of the factory method pattern:

Participants

Participant to this pattern are as follows:

  • Product interface: This class contains the definition of our product. We will define what a card is here.

  • Abstract product: This abstract class implements the signature of our cards and some methods. You'll see that we keep the prototype pattern that allows us to eventually clone a card. These classes define the properties of our products.

  • Concrete product: This class defines our product; in our example, the Raid Leader card is a concrete product, such as the Faceless Manipulator card.

  • Concrete creator: This class implements our factory method.

Illustration

In our previous pattern, you would have seen the following line:

let raidLeader = Card(name: "Raid Leader", mana: 3, attack: 2, defense: 2)

Here, we directly program an implementation. We need a way to create some cards, but without having the knowledge to know exactly how to construct the card; we can only tell to create the raidLeader and Faceless Manipulator cards. At this point of time, the client doesn't want to know that the Raid Leader card needs three manas, so it provides two points of attack and two points of defense.

Implementation

The implementation of the factory method pattern is as follows:

import UIKit
import Foundation

//Define what a card is
protocol Card {
  var name: String? {get set}
  var attack: Int? {get set}
  var defense: Int? {get set}
  var mana: Int? {get set}
  func clone() -> Card
  func toString() -> String
}

// AbstractCard
// implements the signature and some properties
class AbstractCard: NSObject, Card {
  private var _name: String?
  private var _mana: Int?
  private var _attack: Int?
  private var _defense: Int?
  
  init(name: String?, mana: Int?, attack: Int?, defense: Int?) {
    self._name = name
    self._attack = attack
    self._defense = defense
    self._mana = mana
    super.init()
  }
 
  override init(){
    super.init()
  }
  
  //property name
  var name: String?{
    get{ return _name }
    set{ _name = newValue }
  }
  
  //property mana
  var mana: Int? {
    get{ return _mana }
    set{ _mana = newValue }
  }
  
  //property attack
  var attack: Int? {
    get{ return _attack }
    set{ _attack = newValue }
  }
  
  //property attack
  var defense: Int? {
    get{ return _defense }
    set{ _defense = newValue }
  }
  
  func clone() -> Card {
    return AbstractCard(name: self.name, mana: self.mana, attack: self.attack, defense: self.defense)
  }
  
  func toString() -> String{
    return ("\(self.name, self.mana, self.attack,self.defense)")
  }
}

enum CardType {
  case FacelessManipulator, RaidLeader
}

// our Factory Class
// Depending what we need, this class return an instance of the 
// appropriate object.
class CardFactory{
  class func createCard(cardtype: CardType) -> Card?{
    
    switch cardtype {
    case .FacelessManipulator:
      return FacelessManipulatorCard()
    case .RaidLeader:
      return RaidLeaderCard()
    default:
      return nil
    }
  }
}

//Concrete Card "Raid Leader"
//This is the full definition of the Raid Leader Card
class RaidLeaderCard: AbstractCard {
  override init()
  {
    super.init()
    self._mana = 3
    self._attack = 2
    self._defense = 2
    self._name = "Raid Leader"
  }
}

//Concrete Card "Faceless Manipulator"
//this is the full definition of the FacelessManipulator Card.
class FacelessManipulatorCard: AbstractCard {
  override init()
  {
    super.init()
    self._mana = 5
    self._attack = 3
    self._defense = 3
    self._name = "Faceless Manipulator"
    
  }
}

Usage

To simulate the use of the factory method pattern by a client, we can write the card creation as follows:

//simulate our client

var c = CardFactory.createCard(.FacelessManipulator)
c?.toString()

Note

To simulate our client, we simply tell the CardFactory method that we want a FacelessManipulator card.

To do this, we use the createCard method (our factory method), and this method will delegate the instantiation of the card that was asked.

The variable c has the type Card and not FacelessManipulator.

 

The singleton pattern


This pattern is certainly the pattern that every developer learns first. It is often used with a factory or abstract factory class to ensure that there is only one instance of the class.

Roles

The singleton pattern ensures that a class has only one instance and provides a global point of access to it, and at this point, it returns an instance of this class.

In some cases, it can be useful to have some classes that have only one instance; for example, in the case of the abstract factory, where it is not useful to have several instances.

Design

The following figure shows the generic UML class diagram of the singleton pattern. There are many way to write the singleton pattern using Swift.

Here, we use the easiest way to do this. With Swift, you'll see that we can change the way in which we apply it, thanks to the class constant:

Participants

There is only one participant in this pattern: the Singleton class.

This class provides a method that returns only one instance of the class. The mechanism locks the creation of other instances. It was introduced with Swift 1.2. We can now use class constants.

With Swift 1.2, we will use the class constants to provide us with a way to ensure the unique creation of the instance.

A class constant is defined as follows:

static let myVariable = myObject()

Collaborations

Every client will have access to the unique instance of the Singleton class by calling the Instance method.

With Swift, the approach we'll consider is the one that accesses our unique instance of the Singleton class using the class constant that we will call sharedInstance.

Illustration

You are developing your card game and you need to manage all the data of the current game. In our game, we have two players; each player has a deck, mana reserve, name, and so on. We have a board (the table where we put our cards) and a game state (who is currently playing). To manage all of this information, you'll need a BoardManager class. This class will be a singleton class because we will not have several boards at the same time (we only allow one game at a time). The singleton pattern can be something interesting that can be used here in order to make sure that we access the good data.

Implementation

The following approach supports lazy initialization, and it is thread safe by the definition of let:

import UIKit

class BoardGameManager {
  
  static let sharedInstance = BoardGameManager()
  init() {
    println("Singleton initialized");
  }
  
}

Usage

To use our singleton object, each client will access it using the following code :

let boardManager = BoardGameManager.sharedInstance

The boardManager variable contains all the members available in our singleton object and will be initialized only once.

This pattern is used in the following cases:

  • We must have only one instance of a class

  • This instance must be accessible to clients from a well-known access point

 

The abstract factory pattern


We already introduced you to a very popular concept in design patterns: factories. Factories are the classes that handle the instantiation of related objects without subclassing. The factory method pattern that we have already seen hides the class name from where an object is instantiated. The abstract factory pattern is more complete as it creates families of related or dependent objects.

Roles

The abstract factory pattern is designed to build objects grouped in families without having to know the concrete class needed to create the object.

This pattern is generally used in the following domains:

  • A system that uses products needs to stay independent of how these products are grouped and instantiated

  • A system can have several product families that can evolve

Design

The following diagram represents the generic structure of the abstract factory pattern. You will see how products and families are decoupled:

Participants

The abstract factory pattern has a lot of participants:

  • Abstract Factory: This abstract class defines the signature of the different methods that create our products.

  • ConcreteFactory1 and ConcreteFactory2: These are our concrete classes that implement our methods for each products' families. By knowing the family and product, the factory is able to create an instance of the product for that family.

  • IProductA and IProductB: These are our interfaces that define our products that are independent of their family. A family is introduced in their concrete subclasses.

  • ProductA and ProductB: These are the concrete classes that implement IProductA and IProductB, respectively.

Collaborations

The Client class uses one instance of one of the concrete factories to create products throughout the interface of the abstract factory.

Illustration

Our company specializes in manufacturing watches. Our watches are built in two parts: a band and dial. Our watches come in two sizes, so we must adapt the manufacturing of the band and dial according to the size of our watch.

In order to simplify how to manage the manufacturing of our watches, the direction team decided to use one manufacturer who specializes in products that are adapted to the 38 mm model of our watch, and another manufacturer whose products are adapted to the 42 mm model of our watch.

Each of these manufacturers will build a dial and band that are adapted to the dimension of the watch.

Implementation

To implement our pattern, we first need to identify our actors. The two manufacturers represent the ConcreteFactory1 and ConcreteFactory2 classes. These two factories implement the AbstractFactory method, which tell us that we can create a band or dial. Of course, the concrete factories will create the dial adapted to the size of the watch produced in that manufacture.

Our ConcreteProductA and ConcreteProductB classes are the band and the dial; each of these products implements their respective IProductA and IProductB interfaces, as shown in the following code:

import UIKit

//Our interfaces
protocol IWatchBand {
  var color: UIColor{get set}
  var size: BandSize{get set}
  var type: BandType{get set}
  init(size: BandSize)
}

protocol IWatchDial {
  var material: MaterialType{get set}
  var size: WatchSize{get set}
  init(size: WatchSize)
}

//Enums
enum MaterialType: String {
  case Aluminium = "Aluminium",
  StainlessSteel = "Stainless Steel",
  Gold = "Gold"
}

enum BandType: String {
  case Milanese = "Milanese",
  Classic = "Classic",
  Leather = "Leather",
  Modern = "Modern",
  LinkBracelet = "LinkBracelet",
  SportBand = "SportBand"
}

enum WatchSize: String {
  case _38mm = "38mm", _42mm = "42mm"
}

enum BandSize: String {
  case SM = "SM", ML = "ML"
}

//prepare our Bands components
class MilaneseBand: IWatchBand {
  var color = UIColor.yellowColor()
  var size: BandSize
  var type = BandType.Milanese
  required init(size _size: BandSize) {
    size = _size
  }
 }

class Classic: IWatchBand {
  var color = UIColor.yellowColor()
  var size: BandSize
  var type = BandType.Classic
  required init(size _size: BandSize) {
    size = _size
  }
}
class Leather:IWatchBand{
  var color = UIColor.yellowColor()
  var size:BandSize
  var type = BandType.Leather
  required init(size _size: BandSize) {
    size = _size
  }
}
class Modern: IWatchBand {
  var color = UIColor.yellowColor()
  var size: BandSize
  var type = BandType.Modern
  required init(size _size: BandSize) {
    size = _size
  }
}

class LinkBracelet: IWatchBand {
  var color = UIColor.yellowColor()
  var size: BandSize
  var type = BandType.LinkBracelet
  required init(size _size: BandSize) {
    size = _size
  }
}
class SportBand: IWatchBand {
  var color = UIColor.yellowColor()
  var size: BandSize
  var type = BandType.SportBand
  required init(size _size: BandSize) {
    size = _size
  }
}


//Dials
class AluminiumDial: IWatchDial {
  var material: MaterialType = MaterialType.Aluminium
  var size: WatchSize
  required init(size _size:WatchSize){
    size = _size
  }
}

class StainlessSteelDial: IWatchDial {
  var material: MaterialType = MaterialType.StainlessSteel
  var size: WatchSize
  required init(size _size:WatchSize){
    size = _size
  }
}

class GoldDial: IWatchDial {
  var material: MaterialType = MaterialType.Gold
  var size: WatchSize
  required init(size _size:WatchSize){
    size = _size
  }
}


//Our AbstractFactory
class WatchFactory {
  
  func createBand(bandType: BandType) -> IWatchBand {
    fatalError("not implemented")
  }
  func createDial(materialtype: MaterialType) -> IWatchDial{
    fatalError("not implemented")
  }
  
  //our static method that return the appropriated factory.
  final class func getFactory(size: WatchSize) -> WatchFactory{
    var factory: WatchFactory?
    switch(size){
    case ._38mm:
      factory = Watch38mmFactory()
    case ._42mm:
      factory = Watch42mmFactory()
    }
    return factory!
  }

}


// Concrete Factory 1 for 42 mm
class Watch42mmFactory: WatchFactory {
  override func createBand(bandType: BandType) -> IWatchBand {
    switch bandType {
    case .Milanese:
      return MilaneseBand(size: .ML)
    case .Classic:
      return Classic(size: .ML)
    case .Leather:
      return Leather(size: .ML)
    case .LinkBracelet:
      return LinkBracelet(size: .ML)
    case .Modern:
      return Modern(size: .ML)
    case .SportBand:
      return SportBand(size: .ML)
    default:
      return SportBand(size: .ML)
    }
  }
  
  override func createDial(materialtype: MaterialType) -> IWatchDial {
    switch materialtype{
    case MaterialType.Gold:
      return GoldDial(size: ._42mm)
    case MaterialType.StainlessSteel:
      return StainlessSteelDial(size: ._42mm)
    case MaterialType.Aluminium:
      return AluminiumDial(size: ._42mm)
    }
  }
}

//Concrete Factory 2 for 38mm
class Watch38mmFactory: WatchFactory{
  override func createBand(bandType:BandType) -> IWatchBand {
    switch bandType {
    case .Milanese:
      return MilaneseBand(size: .SM)
    case .Classic:
      return Classic(size: .SM)
    case .Leather:
      return Leather(size: .SM)
    case .LinkBracelet:
      return LinkBracelet(size: .SM)
    case .Modern:
      return Modern(size: .SM)
    case .SportBand:
      return SportBand(size: .SM)
    default:
      return SportBand(size: .SM)
    }
  }
  
  override func createDial(materialtype: MaterialType) -> IWatchDial {
    switch materialtype{
    case MaterialType.Gold:
      return GoldDial(size: ._38mm)
    case MaterialType.Gold:
      return StainlessSteelDial(size: ._38mm)
    case MaterialType.Gold:
      return AluminiumDial(size: ._38mm)
    default:
      return AluminiumDial(size: ._38mm)
      
    }
  }
}

Usage

To simulate our client, we will use the following code:

//Here we deliver products from the Manufacture 1 specialized in
//products for the 38 mm Watch
let manufacture1 = WatchFactory.getFactory(WatchSize._38mm)
let productA = manufacture1.createBand(BandType.Milanese)
productA.color
productA.size.rawValue
productA.type.rawValue

let productB = manufacture1.createDial(MaterialType.Gold)
productB.material.rawValue
productB.size.rawValue


//Here we delivers products from the Manufacture 2 specialized in
//products for the 42 mm Watch
let manufacture2 = WatchFactory.getFactory(WatchSize._42mm)
let productC = manufacture2.createBand(BandType.LinkBracelet)
productC.color
productC.size.rawValue
productC.type.rawValue

let productD = manufacture2.createDial(MaterialType.Gold)
productD.material.rawValue
productD.size.rawValue

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

The Playground file will display our product's properties, depending on the factory used. The details of product A (the band) and product B (the dial) from the manufacture1 object are shown in the following screenshot:

The details of product C (the band) and product D (the dial) from the manufacture2 object are shown in the following screenshot:

The sizes of the band and the dial adapt to the manufacturer who delivers the product.

Note

We should use the singleton pattern to ensure that we have only one instance of our abstract factory. This instance can be shared between several clients.

 

The builder pattern


Unlike the abstract factory pattern, which will produce parts of products of the same family, the builder pattern will help us build the finalized product that consists of several parts.

Roles

The main purpose of the builder pattern is to abstract the building of complex objects from its actual construction. Having the same construction process can create different representations of the product.

This pattern can be used when:

  • A client needs to construct complex objects without having to know its implementation

  • A client needs to construct complex objects that need to have several implementations or representations

Design

The following figure shows the generic UML class diagram of the builder pattern:

Participants

This pattern is quite simple as it has only a few participants:

  • Director: This class constructs the product using the interface of the AbstractBuilder class.

  • AbstractBuilder: This class defines the method signature that allows the construction of all the parts of the product, and it contains a signature of a method that returns the product once this is built.

  • ConcreteBuilder: This is the Concrete class that implements the method of the AbstractBuilder class.

  • Product: This is the finalized product. The product contains all the parts of the watch.

Collaborations

The client creates the ConcreteBuilder and Director classes. The Director class will then build an object if the client asks him to do so by invoking the constructor and returns the finalized product to the client.

Illustration

Using the AbstractFactory method, we can use the builder pattern to build a watch. As we've seen that a watch has several parts: a dial and band. A watch can have two sizes too, and as we have already seen, the representation of the dial or band depends on the size of the watch too.

Implementation

If we want to build some watches that are represented with a dial and band, we will define a Director class that will define the construction order of all the parts of our watches and return the finalized watch to the client.

The Director class will call all the constructors who are in charge to construct one part of the watch. To implement this, we will reuse the existing code of the abstract factory pattern and add the following code.

Open the Builder.playground file in Xcode to see the added code at the bottom of the file:

//Our builder1
class BuilderGoldMilanese38mmWatch: AbstractWatchBuilder {
  override func buildDial() {
    watch.band = MilaneseBand(size: BandSize.SM)
  }
  override func buildBand() {
    watch.dial = GoldDial(size: WatchSize._38mm)
  }
}

//Our builder2
class BuilderAluminiumSportand42mmWatch:AbstractWatchBuilder {
  override func buildDial() {
    watch.band = SportBand(size: BandSize.ML)
  }
  override func buildBand() {
    watch.dial = AluminiumDial(size: WatchSize._42mm)
  }
}

//our Director class
class Director {
  var builder: AbstractWatchBuilder?
  init(){
    
  }
  
  func buildWatch(builder: AbstractWatchBuilder){
    builder.buildBand()
    builder.buildDial()
  }
}

Usage

To simulate our client, we will tell our director to create two watches:

  • A 42 mm aluminium dial with a sports band

  • A 38 mm gold dial with a milanese band

The code for the example is as follows:

//We will build 2 Watches :
//First is the Aluminium Dial of 42mm with Sport Band
let director = Director()
var b1 = BuilderAluminiumSportand42mmWatch()
director.buildWatch(b1)

// our watch 1
var w1 = b1.getResult()
w1.band?.color
w1.band?.type.rawValue
w1.band?.size.rawValue
w1.dial?.size.rawValue
w1.dial?.material.rawValue

//Our 2nd watch is a Gold 38mm Dial with Milanese Band
var b2 = BuilderGoldMilanese38mmWatch ()
director.buildWatch(b2)

// Our watch 1
var w2 = b2.getResult()
w2.band?.color
w2.band?.type.rawValue
w2.band?.size.rawValue
w2.dial?.size.rawValue
w2.dial?.material.rawValue

The result is shown in Playground like this:

Note

Swift allows the use of closure that simplifies the creation of our complex objects. Regarding the example that we provided earlier, we can write the following code to build our two watches.

Implementation using closures

Here, we don't need to use the Director and ConcreteBuilder classes. Instead, we will tell our Watch class that the builder will be in the closure.

In the previous example, remove the Director, AbstractBuilder, and ConcreteBuilder classes.

We just need to write the Watch class, as shown in the following code (you can find the following code in the BuilderClosures.playground file accompanying this chapter):

//our Product Class : a Watch
//The builder will be in the closure
class Watch{
  var dial:IWatchDial?
  var band:IWatchBand?
  typealias buildWatchClosure = (Watch) -> Void
  
  init(build:buildWatchClosure){
    build(self)
  }
}

Then, to simulate our client, we can write the following code which will call the appropriate constructor assigned to the band or dial property of the Watch object:

//Simulate our clients

let Gold42mmMilaneseWatch = Watch(build: {
  $0.band = MilaneseBand(size: BandSize.ML)
  $0.dial = GoldDial(size: WatchSize._42mm)
})

The result is as follows:

 

Summary


Well, I hope that this chapter was a good introduction to the use of patterns using Swift. We learned the five creational patterns: the prototype pattern, the factory method pattern, the singleton pattern, the abstract factory pattern, and the builder pattern. We also learned when to use them and how to implement them.

In the next chapter, we will introduce you to three structural patterns that are designed to ease the relationship between entities.

About the Author
  • Julien Lange

    Julien Lange is a 34-year-old IT expert in software engineering. He started developing on an Amstrad CPC464 with the BASIC language when he was 7 years old. He later learned Visual Basic 3/4, then VB.NET, and then C#. For several years until the end of his education, he developed and maintained several e-business websites based on PHP and ASP.NET. After his graduation, he continued to learn more and more about software, which included software architecture and project management, and always tried to acquire new skills. Since 2011, he has been working as an IT project manager on the lead management middleware of DSI Axa France (a French insurance company). This middleware is based on the SOA architecture. As this middleware is consumed by frontend users exposed on the Internet, performance is the top priority each time he delivers a new release of the system. Scalability and robustness are really important in his everyday work. He first developed an interest in mobile development in 2009. After discovering the massive potential of iPhone games and software, he decided to find an improved game engine, which would allow him to concentrate only on the main purpose of a game: developing a game and not a game engine. His choice was Unity 3D. Later, he took some time to learn the native iOS Objective-C language, which was quite difficult for him due to its language particularity and finally learned Swift since its first apparition in 2014. In addition to his main work as an IT consultant, he created iXGaming.com in December 2010. He currently has several projects in mind, including a game based on a French board game and a new website that delivers new services to developers. He is searching for a few partners to work with.

    Browse publications by this author
Latest Reviews (7 reviews total)