Design Patterns In Swift
π Design Patterns implemented in Swift 5.0
Install / Use
npx skills add ochococo/Design-Patterns-In-SwiftInstalls into whichever agent you are using.
README
Design Patterns implemented in Swift 5.0
A short cheat-sheet with Xcode 10.2 Playground (Design-Patterns.playground.zip).
π¨π³δΈζη
π· Project started by: @nsmeme (Oktawian Chojnacki)
π· δΈζηη± @binglogo (ζ£ζ£ε½¬) ζ΄ηηΏ»θ―γ
π How to generate README, Playground and zip from source: CONTRIBUTING.md
print("Welcome!")
Table of Contents
| Behavioral | Creational | Structural | | ------------------------------------------------------ | ---------------------------------------- | ---------------------------------------- | | π Chain Of Responsibility | π° Abstract Factory | π Adapter | | π« Command | π· Builder | π Bridge | | πΆ Interpreter | π Factory Method | πΏ Composite | | π« Iterator | π Monostate | π§ Decorator | | π Mediator | π Prototype | π FaΓ§ade | | πΎ Memento | π Singleton | π Flyweight | | π Observer | | β Protection Proxy | | π State | | π¬ Virtual Proxy | | π‘ Strategy | | | | π Template Method | | | | π Visitor | | |
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
The chain of responsibility pattern is used to process varied requests, each of which may be dealt with by a different handler.
Example:
protocol Withdrawing {
func withdraw(amount: Int) -> Bool
}
final class MoneyPile: Withdrawing {
let value: Int
var quantity: Int
var next: Withdrawing?
init(value: Int, quantity: Int, next: Withdrawing?) {
self.value = value
self.quantity = quantity
self.next = next
}
func withdraw(amount: Int) -> Bool {
var amount = amount
func canTakeSomeBill(want: Int) -> Bool {
return (want / self.value) > 0
}
var quantity = self.quantity
while canTakeSomeBill(want: amount) {
if quantity == 0 {
break
}
amount -= self.value
quantity -= 1
}
guard amount > 0 else {
return true
}
if let next {
return next.withdraw(amount: amount)
}
return false
}
}
final class ATM: Withdrawing {
private var hundred: Withdrawing
private var fifty: Withdrawing
private var twenty: Withdrawing
private var ten: Withdrawing
private var startPile: Withdrawing {
return self.hundred
}
init(hundred: Withdrawing,
fifty: Withdrawing,
twenty: Withdrawing,
ten: Withdrawing) {
self.hundred = hundred
self.fifty = fifty
self.twenty = twenty
self.ten = ten
}
func withdraw(amount: Int) -> Bool {
return startPile.withdraw(amount: amount)
}
}
Usage
// Create piles of money and link them together 10 < 20 < 50 < 100.**
let ten = MoneyPile(value: 10, quantity: 6, next: nil)
let twenty = MoneyPile(value: 20, quantity: 2, next: ten)
let fifty = MoneyPile(value: 50, quantity: 2, next: twenty)
let hundred = MoneyPile(value: 100, quantity: 1, next: fifty)
// Build ATM.
var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten)
atm.withdraw(amount: 310) // Cannot because ATM has only 300
atm.withdraw(amount: 100) // Can withdraw - 1x100
π« Command
The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use.
Example:
protocol DoorCommand {
func execute() -> String
}
final class OpenCommand: DoorCommand {
let doors:String
required init(doors: String) {
self.doors = doors
}
func execute() -> String {
return "Opened \(doors)"
}
}
final class CloseCommand: DoorCommand {
let doors:String
required init(doors: String) {
self.doors = doors
}
func execute() -> String {
return "Closed \(doors)"
}
}
final class HAL9000DoorsOperations {
let openCommand: DoorCommand
let closeCommand: DoorCommand
init(doors: String) {
self.openCommand = OpenCommand(doors:doors)
self.closeCommand = CloseCommand(doors:doors)
}
func close() -> String {
return closeCommand.execute()
}
func open() -> String {
return openCommand.execute()
}
}
Usage:
let podBayDoors = "Pod Bay Doors"
let doorModule = HAL9000DoorsOperations(doors:podBayDoors)
doorModule.open()
doorModule.close()
πΆ Interpreter
The interpreter pattern is used to evaluate sentences in a language.
Example
protocol IntegerExpression {
func evaluate(_ context: IntegerContext) -> Int
func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression
func copied() -> IntegerExpression
}
final class IntegerContext {
private var data: [Character:Int] = [:]
func lookup(name: Character) -> Int {
return self.data[name]!
}
func assign(expression: IntegerVariableExpression, value: Int) {
self.data[expression.name] = value
}
}
final class IntegerVariableExpression: IntegerExpression {
let name: Character
init(name: Character) {
self.name = name
}
func evaluate(_ context: IntegerContext) -> Int {
return context.lookup(name: self.name)
}
func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression {
if name == self.name {
return integerExpression.copied()
} else {
return IntegerVariableExpression(name: self.name)
}
}
func copied() -> IntegerExpression {
return IntegerVariableExpression(name: self.name)
}
}
final class AddExpression: IntegerExpression {
private var operand1: IntegerExpression
private var operand2: IntegerExpression
init(op1: IntegerExpression, op2: IntegerExpression) {
self.operand1 = op1
self.operand2 = op2
}
func evaluate(_ context: IntegerContext) -> Int {
return self.operand1.evaluate(context) + self.operand2.evaluate(context)
}
func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression {
return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression),
op2: operand2.replace(character: character, integerExpression: integerExpression))
}
func copied() -> IntegerExpression {
return AddExpression(op1: self.operand1, op2: self.operand2)
}
}
Usage
var context = IntegerContext()
var a = IntegerVariableExpression(name: "A")
var b = IntegerVariableExpression(name: "B")
var c = IntegerVariableExpression(name: "C")
var expression = AddExpression(op1: a, op2: AddExpression(op1: b, op2: c)) // a + (b + c)
context.assign(expression: a, value: 2)
context.assign(expression: b, value: 1)
context.assign(expression: c, value: 3)
var result = expression.evaluate(context)
π« Iterator
The iterator pattern is used to provide a standard interface for traversing a collection of items in an aggregate object without the need to understand its underlying structure.
Example:
struct Novella {
let name: String
}
struct Novellas {
let novellas: [Novella]
}
struct NovellasIterator: IteratorProtocol {
private var current = 0
private let novellas: [Novella]
init(novellas: [Novella]) {
self.novellas = novellas
}
mutating func next() -> Novella? {
defer { current += 1 }
return novellas.count > current ? novellas[current] : nil
}
}
extension Novellas: Sequence {
func makeIterator() -> NovellasIterator {
return NovellasIterator(novellas: novellas)
}
}
Usage
let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] )
for novella in greatNovellas {
print("I've rea
Related Skills
obsidian
385.5kWork with Obsidian vaults using the official obsidian CLI: read/search/create/edit notes, tasks, links, properties, plugins.
html-anything
8.1kβ¨ The agentic HTML editor β your local AI agent writes the HTML, you ship it. π 75 Skills Γ 9 Surfaces (magazine Β· deck Β· poster Β· XHS / tweet Β· prototype Β· data report Β· Hyperframes) π‘οΈ Sandboxed preview Β· π€ 1-click to WeChat / X / Zhihu / HTML / PNG π Zero API key β Claude Code / Cursor / Codeβ¦
openpencil
4.7kThe world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
openpencil
4.7kThe world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
