import Swift
import Foundation
A short cheat-sheet with Xcode 6 Playground (Design-Patterns.playground.zip).
π· Project maintained by: @nsmeme (Oktawian Chojnacki)
πΊ Playground generated with: Swift Playground Builder by @jasonsandmeyer
π How to generate playground (+zip) from this README: GENERATE.markdown
In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.
Source: wikipedia.org
##π Singleton
class SingletonClass {
class var shared : SingletonClass {
struct Static {
static let instance : SingletonClass = SingletonClass()
}
return Static.instance
}
}
Usage:
let instance = SingletonClass.shared
##π· Builder
protocol ThreeDimensions {
var x: Double? {get}
var y: Double? {get}
var z: Double? {get}
}
class Point : ThreeDimensions {
var x: Double?
var y: Double?
var z: Double?
typealias PointBuilderClosure = (Point) -> ()
init(buildClosure: PointBuilderClosure) {
buildClosure(self)
}
}
Usage:
let fancyPoint = Point { point in
point.x = 0.1
point.y = 0.2
point.z = 0.3
}
fancyPoint.x
fancyPoint.y
fancyPoint.z
Shorter but oh-so-ugly alternative:
let uglierPoint = Point {
$0.x = 0.1
$0.y = 0.2
$0.z = 0.3
}
##π° Abstract Factory
class Number {
var number: AnyObject
init(number:AnyObject) {
self.number = number
}
convenience init(integer: Int) {
self.init(number: integer)
}
convenience init(double: Double) {
self.init(number: double)
}
func integerValue() -> Int {
return self.number as Int
}
func doubleValue() -> Double {
return self.number as Double
}
}
Usage:
let number = Number(double: 12.1)
let double = number.doubleValue()
let integer = number.integerValue()
##π Prototype
class ThieveryCorporationPersonDisplay {
var name: String?
let font: String
init(font: String) {
self.font = font
}
func clone() -> ThieveryCorporationPersonDisplay {
return ThieveryCorporationPersonDisplay(font:self.font)
}
}
Usage:
let Prototype = ThieveryCorporationPersonDisplay(font:"Ubuntu")
let Philippe = Prototype.clone()
Philippe.name = "Philippe"
let Christoph = Prototype.clone()
Christoph.name = "Christoph"
let Eduardo = Prototype.clone()
Eduardo.name = "Eduardo"
##π Factory Method
protocol Currency {
func symbol() -> String
func code() -> String
}
class Euro : Currency {
func symbol() -> String {
return "β¬"
}
func code() -> String {
return "EUR"
}
}
class UnitedStatesDolar : Currency {
func symbol() -> String {
return "$"
}
func code() -> String {
return "USD"
}
}
enum Country {
case UnitedStates, Spain, France, UK
}
class CurrencyFactory {
class func currencyForCountry(country:Country) -> Currency? {
switch country {
case .Spain, .France :
return Euro()
case .UnitedStates :
return UnitedStatesDolar()
default:
return nil
}
}
}
Usage:
let noCurrencyCode = "No Currency Code Available"
CurrencyFactory.currencyForCountry(.Spain)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.UnitedStates)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.France)?.code() ?? noCurrencyCode
CurrencyFactory.currencyForCountry(.UK)?.code() ?? noCurrencyCode
#Structural
In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.
Source: wikipedia.org
##πΏ Composite
/**
* Component
*/
protocol Shape {
func draw(fillColor: String)
}
/**
* Leafs
*/
class Square : Shape {
func draw(fillColor: String) {
print("Drawing a Square with color \(fillColor)")
}
}
class Circle : Shape {
func draw(fillColor: String) {
print("Drawing a circle with color \(fillColor)")
}
}
/**
* Composite
*/
class Whiteboard : Shape {
lazy var shapes = [Shape]()
init(_ shapes:[Shape]) {
self.shapes = shapes
}
func draw(fillColor:String) {
for shape in self.shapes {
shape.draw(fillColor)
}
}
}
Usage:
var whiteboard = Whiteboard([Circle(), Square()])
whiteboard.draw("Red")
##π FaΓ§ade
class Eternal {
class func setObject(value: AnyObject!, forKey defaultName: String!) {
let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(value, forKey:defaultName)
defaults.synchronize()
}
class func objectForKey(defaultName: String!) -> AnyObject! {
let defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
return defaults.objectForKey(defaultName)
}
}
Usage:
Eternal.setObject("Disconnect me. Iβd rather be nothing", forKey:"Bishop")
Eternal.objectForKey("Bishop")
##π Adapter
// WARNING: This example uses Point class from Builder pattern!
class PointConverter {
class func convert(#point:Point, base:Double, negative:Bool) -> Point{
var pointConverted = Point{
if let x = point.x{ $0.x = x * base * (negative ? -1.0 : 1.0) }
if let y = point.y{ $0.y = y * base * (negative ? -1.0 : 1.0) }
if let z = point.z{ $0.z = z * base * (negative ? -1.0 : 1.0) }
}
return pointConverted
}
}
extension PointConverter{
class func convert(#x:Double!, y:Double!, z:Double!, base:Double!, negative:Bool!) -> (x:Double!,y:Double!,z:Double!){
var point = Point{ $0.x = x; $0.y = y; $0.z = z }
var pointCalculated = self.convert(point:point, base:base, negative:negative)
return (pointCalculated.x!,pointCalculated.y!,pointCalculated.z!)
}
}
Usage:
var tuple = PointConverter.convert(x:1.1, y:2.2, z:3.3, base:2.0, negative:true)
tuple.x
tuple.y
tuple.z
##π§ Bridge ##π§ Decorator ##π§ Proxy
#Behavioral
In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.
Source: wikipedia.org
##π§ Chain Of Responsibility ##π« Command
protocol FileOperationCommand {
init(file: String)
func execute()
}
class FileMoveCommand : FileOperationCommand {
let file:String
required init(file: String) {
self.file = file
}
func execute() {
print("\(file) moved")
}
}
class FileDeleteCommand : FileOperationCommand {
let file:String
required init(file: String) {
self.file = file
}
func execute() {
print("\(file) deleted")
}
}
class FileManager {
let deleteCommand: FileOperationCommand
let moveCommand: FileOperationCommand
init(deleteCommand: FileDeleteCommand, moveCommand: FileMoveCommand) {
self.deleteCommand = deleteCommand
self.moveCommand = moveCommand
}
func delete () {
deleteCommand.execute()
}
func move () {
moveCommand.execute()
}
}
Usage:
let deleteCommand = FileDeleteCommand(file: "/path/to/testfile")
let moveCommand = FileMoveCommand(file: "/path/to/testfile")
let fileManager = FileManager(deleteCommand:deleteCommand , moveCommand: moveCommand)
fileManager.delete()
fileManager.move()
##π§ Iterator ##π§ Mediator ##π§ Memento ##π§ Observer ##π State
class Context {
private var state: State = UnauthorizedState()
func changeStateToAuthorized(#userId: String) {
state = AuthorizedState(userId: userId)
}
func changeStateToUnauthorized() {
state = UnauthorizedState()
}
var isAuthorized: Bool {
get { return state.isAuthorized(self) }
}
var userId: String? {
get { return state.userId(self) }
}
}
protocol State {
func isAuthorized(context: Context) -> Bool
func userId(context: Context) -> String?
}
class UnauthorizedState: State {
func isAuthorized(context: Context) -> Bool { return false }
func userId(context: Context) -> String? { return nil }
}
class AuthorizedState: State {
let userId: String
init(userId: String) { self.userId = userId }
func isAuthorized(context: Context) -> Bool { return true }
func userId(context: Context) -> String? { return userId }
}
Usage:
let context = Context()
(context.isAuthorized, context.userId)
context.changeStateToAuthorized(userId: "admin")
(context.isAuthorized, context.userId) // now logged in as "admin"
context.changeStateToUnauthorized()
(context.isAuthorized, context.userId)
##π‘ Strategy
protocol PrintStrategy {
func printString(string: String) -> String
}
class Printer {
let strategy: PrintStrategy
func printString(string:String) -> String {
return self.strategy.printString(string)
}
init(strategy: PrintStrategy) {
self.strategy = strategy
}
}
class UpperCaseStrategy: PrintStrategy {
func printString(string:String) -> String {
return string.uppercaseString
}
}
class LowerCaseStrategy: PrintStrategy {
func printString(string:String) -> String {
return string.lowercaseString
}
}
Usage:
var lower = Printer(strategy: LowerCaseStrategy())
lower.printString("O tempora, o mores!")
var upper = Printer(strategy: UpperCaseStrategy())
upper.printString("O tempora, o mores!")
##π Visitor
protocol PlanetVisitor {
func visit(planet: PlanetEarth)
func visit(planet: PlanetMars)
func visit(planet: PlanetGliese581C)
}
protocol Planet {
func accept(visitor: PlanetVisitor)
}
class PlanetEarth: Planet {
func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetMars: Planet {
func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class PlanetGliese581C: Planet {
func accept(visitor: PlanetVisitor) { visitor.visit(self) }
}
class NameVisitor: PlanetVisitor {
var name = ""
func visit(planet: PlanetEarth) { name = "Earth" }
func visit(planet: PlanetMars) { name = "Mars" }
func visit(planet: PlanetGliese581C) { name = "Gliese 581 C" }
}
Usage:
let planets: [Planet] = [PlanetEarth(), PlanetMars(), PlanetGliese581C()]
let names = planets.map { (planet: Planet) -> String in
let visitor = NameVisitor()
planet.accept(visitor)
return visitor.name
}
names