├── 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
--------------------------------------------------------------------------------