Skip to main content

Example 2

import XCTest

class FactoryMethodRealWorld: XCTestCase {

func testFactoryMethodRealWorld() {

let info = "Very important info of the presentation"

let clientCode = ClientCode()

/// Present info over WiFi
clientCode.present(info: info, with: WifiFactory())

/// Present info over Bluetooth
clientCode.present(info: info, with: BluetoothFactory())
}
}

protocol ProjectorFactory {

func createProjector() -> Projector

func syncedProjector(with projector: Projector) -> Projector
}

extension ProjectorFactory {

/// Base implementation of ProjectorFactory

func syncedProjector(with projector: Projector) -> Projector {

/// Every instance creates an own projector
let newProjector = createProjector()

/// sync projectors
newProjector.sync(with: projector)

return newProjector
}
}

class WifiFactory: ProjectorFactory {

func createProjector() -> Projector {
return WifiProjector()
}
}

class BluetoothFactory: ProjectorFactory {

func createProjector() -> Projector {
return BluetoothProjector()
}
}

protocol Projector {

/// Abstract projector interface

var currentPage: Int { get }

func present(info: String)

func sync(with projector: Projector)

func update(with page: Int)
}

extension Projector {

/// Base implementation of Projector methods

func sync(with projector: Projector) {
projector.update(with: currentPage)
}
}

class WifiProjector: Projector {

var currentPage = 0

func present(info: String) {
print("Info is presented over Wifi: \(info)")
}

func update(with page: Int) {
/// ... scroll page via WiFi connection
/// ...
currentPage = page
}
}

class BluetoothProjector: Projector {

var currentPage = 0

func present(info: String) {
print("Info is presented over Bluetooth: \(info)")
}

func update(with page: Int) {
/// ... scroll page via Bluetooth connection
/// ...
currentPage = page
}
}

private class ClientCode {

private var currentProjector: Projector?

func present(info: String, with factory: ProjectorFactory) {

/// Check wheater a client code already present smth...

guard let projector = currentProjector else {

/// 'currentProjector' variable is nil. Create a new projector and
/// start presentation.

let projector = factory.createProjector()
projector.present(info: info)
self.currentProjector = projector
return
}

/// Client code already has a projector. Let's sync pages of the old
/// projector with a new one.

self.currentProjector = factory.syncedProjector(with: projector)
self.currentProjector?.present(info: info)
}
}
Info is presented over Wifi: Very important info of the presentation
Info is presented over Bluetooth: Very important info of the presentation