├── Adapter.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Chain of Responsibility.playground ├── Contents.swift └── contents.xcplayground ├── Command.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Composite.playground ├── Contents.swift └── contents.xcplayground ├── Decorator.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ ├── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate │ └── artemkirillov.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Facade.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Flyweight.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── artemkirillov.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Iterator.playground ├── Pages │ ├── 1.xcplaygroundpage │ │ └── Contents.swift │ └── 2.xcplaygroundpage │ │ └── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── LICENSE ├── Mediator.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Memento.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Observer.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Prototype.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Proxy.playground ├── Contents.swift └── contents.xcplayground ├── README.md ├── Singleton.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ ├── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate │ └── artemkirillov.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── State.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── artemkirillov.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Strategy.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Template Method.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── a11.xcuserdatad │ └── UserInterfaceState.xcuserstate └── Visitor.playground ├── Contents.swift ├── contents.xcplayground └── playground.xcworkspace ├── contents.xcworkspacedata └── xcuserdata └── artemkirillov.xcuserdatad └── UserInterfaceState.xcuserstate /Adapter.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | protocol BMRImperialCalculation { 2 | func bmr(height: Double, weight: Double, age: Int) -> Int 3 | } 4 | 5 | struct BMRCalculator: BMRImperialCalculation { 6 | func bmr(height: Double, weight: Double, age: Int) -> Int { 7 | return Int(66 + (6.2 * weight) + (12.7 * height) - (6.76 * Double(age))) 8 | } 9 | } 10 | 11 | protocol BMRMetricCalculation { 12 | func metricBMR(height: Double, weight: Double, age: Int) -> String 13 | } 14 | 15 | struct BMRCalculatorAdapter: BMRMetricCalculation { 16 | 17 | private var adaptee: BMRImperialCalculation 18 | 19 | init(adaptee: BMRImperialCalculation) { 20 | self.adaptee = adaptee 21 | } 22 | 23 | func metricBMR(height: Double, weight: Double, age: Int) -> String { 24 | let eHeight = height * 3.28084 25 | let eWeight = weight * 2.20462 26 | let result = adaptee.bmr(height: eHeight, weight: eWeight, age: age) 27 | return "BMR is \(result). \(result > 1000 ? "High." : "Low.")" 28 | } 29 | } 30 | 31 | struct Person { 32 | func checkBMR(calculator: BMRMetricCalculation) { 33 | print(calculator.metricBMR(height: 1.84, weight: 73, age: 26)) 34 | } 35 | } 36 | 37 | let person = Person() 38 | person.checkBMR(calculator: BMRCalculatorAdapter(adaptee: BMRCalculator())) 39 | 40 | -------------------------------------------------------------------------------- /Adapter.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Adapter.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Adapter.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Adapter.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Chain of Responsibility.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Responder { 2 | private var qa: [String: String] 3 | private var next: Responder? 4 | 5 | init(qa: [String: String]) { 6 | self.qa = qa 7 | } 8 | 9 | func setNext(_ next: Responder) { 10 | self.next = next 11 | } 12 | 13 | func answer(for question: String) -> String { 14 | if let answer = qa[question] { 15 | print("--- Done.") 16 | return answer 17 | } else if let next = next { 18 | print("--- Can't handle. Processing to the next...") 19 | return next.answer(for: question) 20 | } 21 | print("--- No answer") 22 | return "Sorry! We'll call you later" 23 | } 24 | } 25 | 26 | final class CallCenter { 27 | private var answerPhone: Responder 28 | private var manager: Responder 29 | private var expert: Responder 30 | 31 | init(answerPhone: Responder, manager: Responder, expert: Responder) { 32 | self.answerPhone = answerPhone 33 | self.manager = manager 34 | self.expert = expert 35 | } 36 | 37 | func receiveCall(question: String) { 38 | print("Answer: \(answerPhone.answer(for: question))") 39 | } 40 | } 41 | 42 | let answerPhone = Responder(qa: [ 43 | "How to turn it on?": "Push the green button", 44 | "How to turn it off?": "Push the red button" 45 | ]) 46 | let manager = Responder(qa: ["I wanna refresh profile info": "Let's get on with it"]) 47 | let expert = Responder(qa: ["Very specific tech question": "Specific answer"]) 48 | 49 | answerPhone.setNext(manager) 50 | manager.setNext(expert) 51 | 52 | let callCenter = CallCenter(answerPhone: answerPhone, manager: manager, expert: expert) 53 | callCenter.receiveCall(question: "How to fire you?") 54 | -------------------------------------------------------------------------------- /Chain of Responsibility.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Command.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | final class LightOutside { 2 | var intensity: Double = 1.0 3 | 4 | func switchOn() { 5 | print("Ligth's switched on") 6 | } 7 | func switchOff() { 8 | print("Light's switched off") 9 | } 10 | } 11 | 12 | final class HeatingCooling { 13 | var temperature: Double = 21.5 14 | var mode: String { 15 | return temperature >= 25 ? "heating" : "cooling" 16 | } 17 | 18 | func start() { 19 | print("Start \(mode)") 20 | } 21 | 22 | func stop() { 23 | print("Stop \(mode)") 24 | } 25 | } 26 | 27 | protocol Command { 28 | func execute() 29 | } 30 | 31 | final class SwitchOnLightCommand: Command { 32 | var light: LightOutside 33 | 34 | init(light: LightOutside) { 35 | self.light = light 36 | } 37 | 38 | func execute() { 39 | light.switchOn() 40 | } 41 | } 42 | 43 | final class StartHeatingCommand: Command { 44 | var heater: HeatingCooling 45 | 46 | init(heater: HeatingCooling) { 47 | self.heater = heater 48 | } 49 | 50 | func execute() { 51 | if heater.temperature < 25 { 52 | heater.temperature = 25 53 | } 54 | heater.start() 55 | } 56 | } 57 | 58 | final class Programm { 59 | var commands: [Command] = [] 60 | 61 | func start() { 62 | commands.forEach { $0.execute() } 63 | } 64 | } 65 | 66 | let light = LightOutside() 67 | let heater = HeatingCooling() 68 | 69 | let lightOnCommand = SwitchOnLightCommand(light: light) 70 | let heatCommand = StartHeatingCommand(heater: heater) 71 | 72 | let eveningProgramm = Programm() 73 | eveningProgramm.commands.append(lightOnCommand) 74 | eveningProgramm.commands.append(heatCommand) 75 | eveningProgramm.start() 76 | -------------------------------------------------------------------------------- /Command.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Command.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Command.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Command.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Composite.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol Component { 4 | var id: UInt32 { get } 5 | func description() -> String 6 | } 7 | 8 | final class WashingMachine: Component { 9 | 10 | var id = arc4random_uniform(100) 11 | 12 | func description() -> String { 13 | return "WashingMachine-\(id)" 14 | } 15 | } 16 | 17 | final class Computer: Component { 18 | 19 | var id = arc4random_uniform(100) 20 | 21 | func description() -> String { 22 | return "Computer-\(id)" 23 | } 24 | } 25 | 26 | final class Speakers: Component { 27 | 28 | var id = arc4random_uniform(100) 29 | 30 | func description() -> String { 31 | return "Speakers-\(id)" 32 | } 33 | } 34 | 35 | final class Composite: Component { 36 | 37 | private var components: [Component] = [] 38 | 39 | func add(component: Component) { 40 | components.append(component) 41 | } 42 | 43 | func remove(component: Component) { 44 | if let index = components.index(where: { $0.id == component.id }) { 45 | components.remove(at: index) 46 | } 47 | } 48 | 49 | var id = arc4random_uniform(100) 50 | 51 | func description() -> String { 52 | return components.reduce("", {"\($0)\($1.description()) "}) 53 | } 54 | } 55 | 56 | let computer = Computer() 57 | let smallBox = Composite() 58 | let mediumBox = Composite() 59 | let bigBox = Composite() 60 | 61 | smallBox.add(component: WashingMachine()) 62 | 63 | mediumBox.add(component: Computer()) 64 | mediumBox.add(component: Speakers()) 65 | 66 | bigBox.add(component: smallBox) 67 | bigBox.add(component: mediumBox) 68 | bigBox.add(component: WashingMachine()) 69 | 70 | print(computer.description()) 71 | print(smallBox.description()) 72 | print(mediumBox.description()) 73 | print(bigBox.description()) 74 | -------------------------------------------------------------------------------- /Composite.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Decorator.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | protocol Coffee { 2 | func cost() -> Double 3 | func ingredients() -> String 4 | } 5 | 6 | final class Espresso: Coffee { 7 | 8 | func ingredients() -> String { 9 | return "Espresso" 10 | } 11 | 12 | func cost() -> Double { 13 | return 100 14 | } 15 | } 16 | 17 | class CoffeDecorator: Coffee { 18 | 19 | private var сoffee: Coffee 20 | 21 | init(сoffee: Coffee) { 22 | self.сoffee = сoffee 23 | } 24 | 25 | func ingredients() -> String { 26 | return сoffee.ingredients() 27 | } 28 | 29 | func cost() -> Double { 30 | return сoffee.cost() 31 | } 32 | } 33 | 34 | final class Milk: CoffeDecorator { 35 | 36 | override func ingredients() -> String { 37 | return super.ingredients() + ", Milk" 38 | } 39 | 40 | override func cost() -> Double { 41 | return super.cost() + 20 42 | } 43 | } 44 | 45 | final class Whip: CoffeDecorator { 46 | 47 | override func ingredients() -> String { 48 | return super.ingredients() + ", Whip" 49 | } 50 | 51 | override func cost() -> Double { 52 | return super.cost() + 30 53 | } 54 | } 55 | 56 | final class Chocolate: CoffeDecorator { 57 | 58 | override func ingredients() -> String { 59 | return super.ingredients() + ", Chocolate" 60 | } 61 | 62 | override func cost() -> Double { 63 | return super.cost() + 50 64 | } 65 | } 66 | 67 | let espresso = Espresso() 68 | let capuccino = Whip(сoffee: Milk(сoffee: espresso)) 69 | let capuccinoWithChocolate = Chocolate(сoffee: capuccino) 70 | 71 | print(espresso.ingredients()) 72 | print(espresso.cost()) 73 | 74 | print(capuccino.ingredients()) 75 | print(capuccino.cost()) 76 | 77 | print(capuccinoWithChocolate.ingredients()) 78 | print(capuccinoWithChocolate.cost()) 79 | -------------------------------------------------------------------------------- /Decorator.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Decorator.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Decorator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Decorator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Decorator.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Decorator.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Facade.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Machine { 2 | enum State { 3 | case notRunning 4 | case ready 5 | case running 6 | } 7 | 8 | private(set) var state: State = .ready 9 | 10 | func startMachine() { 11 | print("Proccessing start...") 12 | state = .ready 13 | state = .running 14 | print("MACHINE IS RUNNING") 15 | } 16 | 17 | func stopMachine() { 18 | print("Proccessing finish...") 19 | state = .notRunning 20 | print("MACHINE STOPPED") 21 | } 22 | } 23 | 24 | final class RequestManager { 25 | 26 | var isConnected: Bool = false 27 | 28 | func connectToTerminal() { 29 | print("Connecting to terminal...") 30 | isConnected = true 31 | } 32 | 33 | func disconnectToTerminal() { 34 | print("Disconnecting to terminal...") 35 | isConnected = false 36 | } 37 | 38 | func getStatusRequest(for machine: Machine) -> Machine.State { 39 | print("Sending status request...") 40 | return machine.state 41 | } 42 | 43 | func sendStartRequest(for machine: Machine) { 44 | print("Sending request to start the machine...") 45 | machine.startMachine() 46 | } 47 | 48 | func sendStopRequest(for machine: Machine) { 49 | print("Sending request to stop the machine...") 50 | machine.stopMachine() 51 | } 52 | } 53 | 54 | protocol Facade { 55 | func startMachine() 56 | } 57 | 58 | final class ConcreteFacade: Facade { 59 | func startMachine() { 60 | let machine = Machine() 61 | let manager = RequestManager() 62 | 63 | if !manager.isConnected { 64 | manager.connectToTerminal() 65 | } 66 | 67 | if manager.getStatusRequest(for: machine) == .ready { 68 | print("MACHINE IS READY") 69 | manager.sendStartRequest(for: machine) 70 | } 71 | } 72 | } 73 | 74 | let simpleInterface = ConcreteFacade() 75 | simpleInterface.startMachine() 76 | -------------------------------------------------------------------------------- /Facade.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Facade.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Facade.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Facade.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Flyweight.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | enum BacteriaType: String { 4 | case cocci 5 | case bacilli 6 | case spirilla 7 | } 8 | 9 | final class BacteriaSprite { 10 | let color: UIColor 11 | let image: UIImage 12 | let type: BacteriaType 13 | 14 | init(color: UIColor, image: UIImage, type: BacteriaType) { 15 | self.color = color 16 | self.image = image 17 | self.type = type 18 | } 19 | 20 | func draw(at point: CGPoint) { 21 | let address = Unmanaged 22 | .passUnretained(self).toOpaque() 23 | print("Draw new bacteria of type \(type.rawValue.capitalized) with sprite object \(address)") 24 | } 25 | } 26 | 27 | final class BacteriaSpriteFactory { 28 | 29 | static private var sprites: [BacteriaType: BacteriaSprite] = [:] { 30 | didSet { 31 | print("Amount of sprites has changed to \(sprites.count)") 32 | } 33 | } 34 | 35 | static func makeBacteriaSprite(for type: BacteriaType) -> BacteriaSprite { 36 | if let sprite = sprites[type] { 37 | return sprite 38 | } else { 39 | var newSprite: BacteriaSprite 40 | switch type { 41 | case .cocci: newSprite = BacteriaSprite(color: .red, image: UIImage(), type: type) 42 | case .bacilli: newSprite = BacteriaSprite(color: .green, image: UIImage(), type: type) 43 | case .spirilla: newSprite = BacteriaSprite(color: .blue, image: UIImage(), type: type) 44 | } 45 | sprites[type] = newSprite 46 | return newSprite 47 | } 48 | } 49 | } 50 | 51 | final class Bacteria { 52 | var point: CGPoint 53 | var size: Double 54 | var sprite: BacteriaSprite 55 | 56 | init(point: CGPoint, size: Double, sprite: BacteriaSprite) { 57 | self.point = point 58 | self.size = size 59 | self.sprite = sprite 60 | } 61 | 62 | func draw() { 63 | sprite.draw(at: point) 64 | } 65 | } 66 | 67 | let bacteriaTypes: [BacteriaType] = [.cocci, .bacilli, .spirilla] 68 | 69 | for _ in 0..<1000 { 70 | let randomType = bacteriaTypes[Int(arc4random_uniform(UInt32(bacteriaTypes.count)))] 71 | let newBacteriaSprite = BacteriaSpriteFactory.makeBacteriaSprite(for: randomType) 72 | let newBacteria = Bacteria(point: .zero, size: 0.3, sprite: newBacteriaSprite) 73 | newBacteria.draw() 74 | } 75 | -------------------------------------------------------------------------------- /Flyweight.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Flyweight.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Flyweight.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Flyweight.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Iterator.playground/Pages/1.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Destination { 2 | let name: String 3 | 4 | init(name: String) { 5 | self.name = name 6 | } 7 | } 8 | 9 | protocol Iterator { 10 | func next() -> Destination? 11 | } 12 | 13 | final class DestinationList { 14 | var destinations: [Destination] 15 | 16 | init(destinations: [Destination]) { 17 | self.destinations = destinations 18 | } 19 | } 20 | 21 | final class DestinationIterator: Iterator { 22 | private var current = 0 23 | private let destinations: [Destination] 24 | 25 | init(destinationList: DestinationList) { 26 | self.destinations = destinationList.destinations 27 | } 28 | 29 | func next() -> Destination? { 30 | let next = current < destinations.count ? destinations[current] : nil 31 | current += 1 32 | return next 33 | } 34 | } 35 | 36 | final class DestinationIterator2: Iterator { 37 | private var current = 0 38 | private let destinations: [Destination] 39 | 40 | init(destinationList: DestinationList) { 41 | self.destinations = destinationList.destinations 42 | self.current = destinations.count - 1 43 | } 44 | 45 | func next() -> Destination? { 46 | let next = current >= 0 ? destinations[current] : nil 47 | current -= 1 48 | return next 49 | } 50 | } 51 | 52 | let list = DestinationList(destinations: [ 53 | Destination(name: "Destination 1"), 54 | Destination(name: "Destination 2"), 55 | Destination(name: "Destination 3") 56 | ] 57 | ) 58 | 59 | var iterator = DestinationIterator(destinationList: list) 60 | var iterator2 = DestinationIterator2(destinationList: list) 61 | 62 | while let element = iterator.next(), let element2 = iterator2.next() { 63 | print("First iterator: \(element.name)") 64 | print("Second iterator: \(element2.name)") 65 | } 66 | -------------------------------------------------------------------------------- /Iterator.playground/Pages/2.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Destination { 2 | let name: String 3 | 4 | init(name: String) { 5 | self.name = name 6 | } 7 | } 8 | 9 | final class DestinationList: Sequence { 10 | var destinations: [Destination] 11 | 12 | init(destinations: [Destination]) { 13 | self.destinations = destinations 14 | } 15 | 16 | func makeIterator() -> DestinationIterator { 17 | return DestinationIterator(destinationList: self) 18 | } 19 | } 20 | 21 | final class DestinationIterator: IteratorProtocol { 22 | private var current = 0 23 | private let destinations: [Destination] 24 | 25 | init(destinationList: DestinationList) { 26 | self.destinations = destinationList.destinations 27 | } 28 | 29 | func next() -> Destination? { 30 | let next = current < destinations.count ? destinations[current] : nil 31 | current += 1 32 | return next 33 | } 34 | } 35 | 36 | final class DestinationIterator2: IteratorProtocol { 37 | private var current: Int 38 | private let destinations: [Destination] 39 | 40 | init(destinationList: DestinationList) { 41 | self.destinations = destinationList.destinations 42 | self.current = destinations.count - 1 43 | } 44 | 45 | func next() -> Destination? { 46 | let next = current >= 0 ? destinations[current] : nil 47 | current -= 1 48 | return next 49 | } 50 | } 51 | 52 | let list = DestinationList(destinations: [ 53 | Destination(name: "Destination 1"), 54 | Destination(name: "Destination 2"), 55 | Destination(name: "Destination 3") 56 | ] 57 | ) 58 | 59 | for destination in list { 60 | print(destination.name) 61 | } 62 | 63 | list.forEach { print($0.name) } 64 | -------------------------------------------------------------------------------- /Iterator.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Iterator.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Iterator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Iterator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Artem Kirillov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mediator.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum Event { 4 | case stepExecuted 5 | case angleChanged 6 | case stabilizationFinished 7 | } 8 | 9 | protocol Mediator { 10 | func notify(sender: Component, event: Event) 11 | } 12 | 13 | protocol Component { 14 | var controller: Mediator? { get set } 15 | } 16 | 17 | final class AngleSensor: Component { 18 | var controller: Mediator? 19 | var value: Double = 0 { 20 | didSet { 21 | controller?.notify(sender: self, event: .angleChanged) 22 | } 23 | } 24 | } 25 | 26 | final class BodyStabilizer: Component { 27 | var controller: Mediator? 28 | 29 | func stabilize() { 30 | print("Stabilizing body\n") 31 | controller?.notify(sender: self, event: .stabilizationFinished) 32 | } 33 | } 34 | 35 | final class MovementRegulator: Component { 36 | var controller: Mediator? 37 | var isCancelled = false 38 | 39 | func executeStep() { 40 | guard !isCancelled else { return } 41 | controller?.notify(sender: self, event: .stepExecuted) 42 | } 43 | } 44 | 45 | final class SystemLogger: Component { 46 | var controller: Mediator? 47 | 48 | func log(pitch: Double) { 49 | print("Logging pitch \(pitch) degrees") 50 | } 51 | } 52 | 53 | final class CentralController: Mediator { 54 | 55 | var pitchAngleSensor: AngleSensor 56 | var rotateAngleSensor: AngleSensor 57 | var healingAngleSensor: AngleSensor 58 | 59 | var stabilizer: BodyStabilizer 60 | var movementRegulator: MovementRegulator 61 | var logger: SystemLogger 62 | 63 | init(pitchAngleSensor: AngleSensor, 64 | rotateAngleSensor: AngleSensor, 65 | healingAngleSensor: AngleSensor, 66 | stabilizer: BodyStabilizer, 67 | movementRegulator: MovementRegulator, 68 | logger: SystemLogger) { 69 | 70 | self.pitchAngleSensor = pitchAngleSensor 71 | self.rotateAngleSensor = rotateAngleSensor 72 | self.healingAngleSensor = healingAngleSensor 73 | 74 | self.stabilizer = stabilizer 75 | self.movementRegulator = movementRegulator 76 | self.logger = logger 77 | } 78 | 79 | func notify(sender: Component, event: Event) { 80 | switch event { 81 | case .stepExecuted: 82 | pitchAngleSensor.value = Double(arc4random_uniform(10)) 83 | case .angleChanged: 84 | let pitchValue = pitchAngleSensor.value 85 | logger.log(pitch: pitchValue) 86 | guard pitchValue > 0 else { 87 | print("Stabilization is not needed\n") 88 | return 89 | } 90 | stabilizer.stabilize() 91 | case .stabilizationFinished: 92 | break 93 | } 94 | } 95 | 96 | func goForward(steps: Int) { 97 | var i = 1 98 | while i <= steps && !movementRegulator.isCancelled { 99 | print("\(i) step forward") 100 | movementRegulator.executeStep() 101 | i += 1 102 | } 103 | } 104 | } 105 | 106 | let pitchAngleSensor = AngleSensor() 107 | let stabilizer = BodyStabilizer() 108 | let movementRegulator = MovementRegulator() 109 | let logger = SystemLogger() 110 | 111 | let controller = CentralController(pitchAngleSensor: pitchAngleSensor, 112 | rotateAngleSensor: AngleSensor(), 113 | healingAngleSensor: AngleSensor(), 114 | stabilizer: stabilizer, 115 | movementRegulator: movementRegulator, 116 | logger: logger) 117 | 118 | pitchAngleSensor.controller = controller 119 | stabilizer.controller = controller 120 | movementRegulator.controller = controller 121 | logger.controller = controller 122 | 123 | controller.goForward(steps: 5) 124 | 125 | -------------------------------------------------------------------------------- /Mediator.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Mediator.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Mediator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Mediator.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Memento.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | struct Point { 4 | var x: Double 5 | var y: Double 6 | } 7 | 8 | final class Painter { 9 | var color: UIColor = .clear 10 | private(set) var paintedPoints: [Point] = [] 11 | 12 | var description: String { 13 | return paintedPoints.reduce("Points: ", { "\($0)(\($1.x); \($1.y)), " }) 14 | } 15 | 16 | func paint(points: [Point]) { 17 | paintedPoints.append(contentsOf: points) 18 | } 19 | 20 | func saveState() -> Memento { 21 | return PainterMemento(color: color, points: paintedPoints) 22 | } 23 | 24 | func restore(state: Memento) { 25 | color = state.color 26 | paintedPoints = state.points 27 | } 28 | } 29 | 30 | protocol Memento { 31 | var color: UIColor { get } 32 | var points: [Point] { get } 33 | } 34 | 35 | final class PainterMemento: Memento { 36 | private(set) var color: UIColor 37 | private(set) var points: [Point] 38 | 39 | init(color: UIColor, points: [Point]) { 40 | self.color = color 41 | self.points = points 42 | } 43 | } 44 | 45 | final class Caretaker { 46 | var states: [Memento] = [] 47 | var currentIndex: Int = 0 48 | var painter: Painter 49 | 50 | init(painter: Painter) { 51 | self.painter = painter 52 | } 53 | 54 | func save() { 55 | let tail = states.count - 1 - currentIndex 56 | if tail > 0 { states.removeLast(tail) } 57 | 58 | states.append(painter.saveState()) 59 | currentIndex = states.count - 1 60 | print("Save. \(painter.description)") 61 | } 62 | 63 | func undo(steps: Int) { 64 | guard steps <= currentIndex else { return } 65 | 66 | currentIndex -= steps 67 | painter.restore(state: states[currentIndex]) 68 | print("Undo \(steps) steps. \(painter.description)") 69 | } 70 | 71 | func redo(steps: Int) { 72 | let newIndex = currentIndex + steps 73 | guard newIndex < states.count - 1 else { return } 74 | 75 | currentIndex = newIndex 76 | painter.restore(state: states[currentIndex]) 77 | print("Redo \(steps) steps. \(painter.description)") 78 | } 79 | } 80 | 81 | let painter = Painter() 82 | let caretaker = Caretaker(painter: painter) 83 | 84 | painter.paint(points: [Point(x: 0, y: 0), Point(x: 1, y: 1)]) 85 | caretaker.save() 86 | 87 | painter.paint(points: [Point(x: 2, y: 2), Point(x: 3, y: 3)]) 88 | caretaker.save() 89 | 90 | painter.paint(points: [Point(x: 4, y: 4), Point(x: 5, y: 5)]) 91 | caretaker.save() 92 | 93 | painter.paint(points: [Point(x: 6, y: 6)]) 94 | caretaker.save() 95 | 96 | caretaker.undo(steps: 3) 97 | caretaker.redo(steps: 1) 98 | 99 | painter.paint(points: [Point(x: 10, y: 10)]) 100 | caretaker.save() 101 | 102 | caretaker.undo(steps: 2) 103 | 104 | -------------------------------------------------------------------------------- /Memento.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Memento.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Memento.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Memento.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Observer.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | protocol Observable { 2 | func add(observer: Observer) 3 | func remove(observer: Observer) 4 | func notifyObservers() 5 | } 6 | 7 | protocol Observer { 8 | var id: String { get set } 9 | func update(value: Int?) 10 | } 11 | 12 | final class NewsResource: Observable { 13 | 14 | var value: Int? { 15 | didSet { 16 | notifyObservers() 17 | } 18 | } 19 | private var observers: [Observer] = [] 20 | 21 | func add(observer: Observer) { 22 | observers.append(observer) 23 | } 24 | 25 | func remove(observer: Observer) { 26 | guard let index = observers.enumerated().first(where: { $0.element.id == observer.id })?.offset else { return } 27 | observers.remove(at: index) 28 | } 29 | 30 | func notifyObservers() { 31 | observers.forEach { $0.update(value: value) } 32 | } 33 | } 34 | 35 | final class NewsAgency: Observer { 36 | var id = "newsAgency" 37 | 38 | func update(value: Int?) { 39 | guard let value = value else { return } 40 | print("NewsAgency handles updated value: \(value)") 41 | } 42 | } 43 | 44 | final class Reporter: Observer { 45 | var id = "reporter" 46 | 47 | func update(value: Int?) { 48 | guard let value = value else { return } 49 | print("Reporter. Updated value: \(value)") 50 | } 51 | } 52 | 53 | final class Blogger: Observer { 54 | var id = "blogger" 55 | 56 | func update(value: Int?) { 57 | guard let value = value else { return } 58 | print("Blogger. New article about value: \(value)") 59 | } 60 | } 61 | 62 | let resource = NewsResource() 63 | let newsAgency = NewsAgency() 64 | let reporter = Reporter() 65 | let blogger = Blogger() 66 | 67 | resource.add(observer: newsAgency) 68 | resource.add(observer: reporter) 69 | 70 | resource.value = 5 71 | 72 | resource.add(observer: blogger) 73 | 74 | resource.value = 7 75 | 76 | resource.remove(observer: reporter) 77 | 78 | resource.value = 11 79 | resource.value = 15 80 | -------------------------------------------------------------------------------- /Observer.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Observer.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Observer.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Observer.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Prototype.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | final class ComplicatedObject { 4 | 5 | private var configuration: Data 6 | 7 | init(url: URL) { 8 | let manager = WebManager() 9 | self.configuration = manager.getData(with: url) 10 | } 11 | 12 | init(object: ComplicatedObject) { 13 | 14 | self.configuration = object.configuration 15 | } 16 | 17 | func clone() -> ComplicatedObject { 18 | return ComplicatedObject(object: self) 19 | } 20 | } 21 | 22 | final class WebManager { 23 | func getData(with url: URL) -> Data { 24 | return Data() 25 | } 26 | } 27 | 28 | let object = ComplicatedObject(url: URL(fileURLWithPath: "")) 29 | let clone = object.clone() 30 | print(object === clone) 31 | -------------------------------------------------------------------------------- /Prototype.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Prototype.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Prototype.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Prototype.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Proxy.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Lock: LockingSystem { 2 | 3 | func open() { 4 | print("Unlock") 5 | } 6 | 7 | func close() { 8 | print("Lock") 9 | } 10 | } 11 | 12 | protocol LockingSystem { 13 | func open() 14 | func close() 15 | } 16 | 17 | final class ProxyLock: LockingSystem { 18 | 19 | private var lock: Lock = Lock() 20 | 21 | func open() { 22 | print("Additional operations...") 23 | lock.open() 24 | } 25 | 26 | func close() { 27 | lock.close() 28 | } 29 | } 30 | 31 | let lock = ProxyLock() 32 | lock.open() 33 | -------------------------------------------------------------------------------- /Proxy.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design Patterns 2 | 3 | Xcode playgrounds with design patterns in Swift. 4 | Additional materials to [YouTube playlist](https://www.youtube.com/watch?v=-bL5MtM9_nQ&list=PLDYxpD3lDWsxWls2_-mwOHLGdtrpqapVJ) 5 | -------------------------------------------------------------------------------- /Singleton.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | final class Singleton { 2 | 3 | static let shared = Singleton() 4 | 5 | private init() { 6 | 7 | } 8 | 9 | var value: Int = 0 10 | 11 | func doSomething() { 12 | print("Doing something with value \(value)") 13 | } 14 | } 15 | 16 | var object = Singleton.shared 17 | object.value = 1000 18 | 19 | var secondObject = Singleton.shared 20 | secondObject.value = 2000 21 | 22 | object.doSomething() 23 | secondObject.doSomething() 24 | 25 | print(object === secondObject) 26 | 27 | //var thirdObject = Singleton() 28 | //thirdObject.value = 9999 29 | //thirdObject.doSomething() 30 | //print(object === thirdObject) 31 | //print(secondObject === thirdObject) 32 | -------------------------------------------------------------------------------- /Singleton.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Singleton.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Singleton.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Singleton.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Singleton.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Singleton.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /State.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol State { 4 | var description: String { get } 5 | 6 | func setTask(_ task: Task) 7 | 8 | func startProgress() 9 | func startTesting() 10 | func close() 11 | func open() 12 | } 13 | 14 | final class OpenState: State { 15 | let description = "Opened at \(Date()) " 16 | private var task: Task? 17 | 18 | init() {} 19 | 20 | func setTask(_ task: Task) { 21 | self.task = task 22 | } 23 | 24 | func startProgress() { task?.setState(InProgressState()) } 25 | func startTesting() { print("--- Needs to start progress.")} 26 | func close() { task?.setState(CloseState()) } 27 | func open() { print("--- Already opened. Do nothing.")} 28 | } 29 | 30 | final class InProgressState: State { 31 | let description = "In progress: \(Date()) " 32 | private var task: Task? 33 | 34 | init() {} 35 | 36 | func setTask(_ task: Task) { 37 | self.task = task 38 | } 39 | 40 | func startProgress() { print("--- Already in progress.") } 41 | func startTesting() { task?.setState(InTestingState()) } 42 | func close() { print("--- Needs to be tested first.") } 43 | func open() { task?.setState(OpenState()) } 44 | } 45 | 46 | final class InTestingState: State { 47 | let description = "Testing: \(Date()) " 48 | private var task: Task? 49 | 50 | init() {} 51 | 52 | func setTask(_ task: Task) { 53 | self.task = task 54 | } 55 | 56 | func startProgress() { task?.setState(InProgressState()) } 57 | func startTesting() { print("--- Already in testing.") } 58 | func close() { task?.setState(CloseState()) } 59 | func open() { print("--- Needs to be closed first.") } 60 | } 61 | 62 | final class CloseState: State { 63 | let description = "Closed at \(Date()) " 64 | private var task: Task? 65 | 66 | init() {} 67 | 68 | func setTask(_ task: Task) { 69 | self.task = task 70 | } 71 | 72 | func startProgress() { task?.setState(InProgressState()) } 73 | func startTesting() { print("--- Needs to be opened first.") } 74 | func close() { print("--- Already closed.") } 75 | func open() { task?.setState(OpenState()) } 76 | } 77 | 78 | final class Task { 79 | var history = "\n Task history:\n" 80 | private var state: State 81 | 82 | init() { 83 | state = OpenState() 84 | state.setTask(self) 85 | history += state.description 86 | print("--- \(state.description)") 87 | } 88 | 89 | func setState(_ state: State) { 90 | self.state = state 91 | state.setTask(self) 92 | history += state.description 93 | print("--- \(state.description)") 94 | } 95 | 96 | func startProgress() { state.startProgress() } 97 | func startTesting() { state.startTesting() } 98 | func close() { state.close() } 99 | func open() { state.open() } 100 | } 101 | 102 | let task = Task() 103 | task.startProgress() 104 | task.startTesting() 105 | task.open() 106 | task.close() 107 | task.startTesting() 108 | task.startProgress() 109 | 110 | print(task.history) 111 | -------------------------------------------------------------------------------- /State.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /State.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /State.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/State.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Strategy.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | final class Filter { 4 | var filterStrategy: FilterStrategy? 5 | 6 | func applyFilter(to image: UIImage) { 7 | filterStrategy?.process(image: image) 8 | } 9 | } 10 | 11 | protocol FilterStrategy { 12 | func process(image: UIImage) -> UIImage 13 | } 14 | 15 | final class SepiaFilter: FilterStrategy { 16 | func process(image: UIImage) -> UIImage { 17 | print("Apply SEPIA filter to image") 18 | return image 19 | } 20 | } 21 | 22 | final class BWFilter: FilterStrategy { 23 | func process(image: UIImage) -> UIImage { 24 | print("Apply B&W filter to image") 25 | return image 26 | } 27 | } 28 | 29 | final class DistortionFilter: FilterStrategy { 30 | func process(image: UIImage) -> UIImage { 31 | print("Apply DISTORTION filter to image") 32 | return image 33 | } 34 | } 35 | 36 | let filter = Filter() 37 | let image = UIImage() 38 | 39 | filter.filterStrategy = SepiaFilter() 40 | filter.applyFilter(to: image) 41 | 42 | filter.filterStrategy = BWFilter() 43 | filter.applyFilter(to: image) 44 | 45 | filter.filterStrategy = DistortionFilter() 46 | filter.applyFilter(to: image) 47 | -------------------------------------------------------------------------------- /Strategy.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Strategy.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Strategy.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Strategy.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Template Method.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | class DataReadingAlgorithm { 2 | 3 | func openResource() { 4 | fatalError("This method must be overriden in subclass") 5 | } 6 | func extractData() { 7 | print("Extracting data...") 8 | } 9 | func parseData() { 10 | print("Parsing data...") 11 | } 12 | func processData() { 13 | print("Processing data...") 14 | } 15 | func closeResource() { 16 | fatalError("This method must be overriden in subclass") 17 | } 18 | 19 | final func readData() { 20 | openResource() 21 | extractData() 22 | parseData() 23 | processData() 24 | closeResource() 25 | } 26 | } 27 | 28 | class FileReader: DataReadingAlgorithm { 29 | 30 | override func openResource() { 31 | print("Open file") 32 | } 33 | 34 | override func closeResource() { 35 | print("Close file\n") 36 | } 37 | } 38 | 39 | class BufferReader: DataReadingAlgorithm { 40 | 41 | override func openResource() { 42 | print("Open buffer") 43 | } 44 | 45 | override func closeResource() { 46 | print("Close buffer\n") 47 | } 48 | } 49 | 50 | class DataBaseReader: DataReadingAlgorithm { 51 | 52 | override func openResource() { 53 | print("Open data base") 54 | } 55 | 56 | override func closeResource() { 57 | print("Close data base\n") 58 | } 59 | } 60 | 61 | let fileReader = FileReader() 62 | fileReader.readData() 63 | 64 | let bufferReader = BufferReader() 65 | bufferReader.readData() 66 | 67 | let dataBaseReader = DataBaseReader() 68 | dataBaseReader.readData() 69 | -------------------------------------------------------------------------------- /Template Method.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Template Method.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Template Method.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Template Method.playground/playground.xcworkspace/xcuserdata/a11.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Visitor.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | final class Report: Visitable { 4 | 5 | var title: String 6 | var illustrations: [Data] 7 | var paragraphs: [String] 8 | var template: [Int: Int] 9 | 10 | init(title: String, illustrations: [Data] = [], 11 | paragraphs: [String] = [], template: [Int: Int] = [:]) { 12 | 13 | self.title = title 14 | self.illustrations = illustrations 15 | self.paragraphs = paragraphs 16 | self.template = template 17 | } 18 | 19 | func accept(visitor: Visitor) { 20 | visitor.visit(report: self) 21 | } 22 | } 23 | 24 | final class SpreadSheet: Visitable { 25 | 26 | var title: String 27 | var structure: [[String]] 28 | 29 | init(title: String, structure: [[String]] = [[]]) { 30 | self.title = title 31 | self.structure = structure 32 | } 33 | 34 | func accept(visitor: Visitor) { 35 | visitor.visit(spreadsheet: self) 36 | } 37 | } 38 | 39 | protocol Visitor { 40 | func visit(report: Report) 41 | func visit(spreadsheet: SpreadSheet) 42 | } 43 | 44 | protocol Visitable { 45 | func accept(visitor: Visitor) 46 | } 47 | 48 | final class HTMLExporter: Visitor { 49 | 50 | func visit(report: Report) { 51 | print("Export report \"\(report.title)\" to HTML") 52 | } 53 | 54 | func visit(spreadsheet: SpreadSheet) { 55 | print("Export spreadsheet \"\(spreadsheet.title)\" to HTML") 56 | } 57 | } 58 | 59 | final class PDFExporter: Visitor { 60 | 61 | func visit(report: Report) { 62 | print("Export report \"\(report.title)\" to PDF") 63 | } 64 | 65 | func visit(spreadsheet: SpreadSheet) { 66 | print("Export spreadsheet \"\(spreadsheet.title)\" to PDF") 67 | } 68 | } 69 | 70 | let report1 = Report(title: "Report 1") 71 | let report2 = Report(title: "Report 2") 72 | let report3 = Report(title: "Report 3") 73 | 74 | let spreadsheet1 = SpreadSheet(title: "SpreadSheet 1") 75 | let spreadsheet2 = SpreadSheet(title: "SpreadSheet 2") 76 | 77 | let htmlExporter = HTMLExporter() 78 | let pdfExporter = PDFExporter() 79 | 80 | let docs: [Visitable] = [report1, report2, report3, spreadsheet1, spreadsheet2] 81 | 82 | docs.forEach { $0.accept(visitor: htmlExporter) } 83 | 84 | print("-----") 85 | 86 | docs.forEach { $0.accept(visitor: pdfExporter) } 87 | -------------------------------------------------------------------------------- /Visitor.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Visitor.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Visitor.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artkirillov/DesignPatterns/47364265c475cabb4d360883d6412f58d5fc934f/Visitor.playground/playground.xcworkspace/xcuserdata/artemkirillov.xcuserdatad/UserInterfaceState.xcuserstate --------------------------------------------------------------------------------