Skip to content

Commit 3f2de97

Browse files
committed
Behavioral Patterns updated to Swift2.
1 parent 51546fd commit 3f2de97

File tree

11 files changed

+414
-358
lines changed

11 files changed

+414
-358
lines changed

Design-Patterns.playground/Pages/Behavioral.xcplaygroundpage/Contents.swift

Lines changed: 198 additions & 166 deletions
Large diffs are not rendered by default.

source/behavioral/chain_of_responsibility.swift

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,70 +6,73 @@ The chain of responsibility pattern is used to process varied requests, each of
66

77
### Example:
88
*/
9-
class MoneyPile {
9+
final class MoneyPile {
10+
1011
let value: Int
1112
var quantity: Int
1213
var nextPile: MoneyPile?
13-
14+
1415
init(value: Int, quantity: Int, nextPile: MoneyPile?) {
1516
self.value = value
1617
self.quantity = quantity
1718
self.nextPile = nextPile
1819
}
19-
20-
func canWithdraw(v: Int) -> Bool {
2120

22-
var v = v
21+
func canWithdraw(amount: Int) -> Bool {
22+
23+
var amount = amount
2324

2425
func canTakeSomeBill(want: Int) -> Bool {
2526
return (want / self.value) > 0
2627
}
27-
28-
var q = self.quantity
2928

30-
while canTakeSomeBill(v) {
29+
var quantity = self.quantity
3130

32-
if q == 0 {
31+
while canTakeSomeBill(want: amount) {
32+
33+
if quantity == 0 {
3334
break
3435
}
3536

36-
v -= self.value
37-
q -= 1
37+
amount -= self.value
38+
quantity -= 1
3839
}
3940

40-
if v == 0 {
41+
guard amount > 0 else {
4142
return true
42-
} else if let next = self.nextPile {
43-
return next.canWithdraw(v)
43+
}
44+
45+
if let next = self.nextPile {
46+
return next.canWithdraw(amount: amount)
4447
}
4548

4649
return false
4750
}
4851
}
4952

50-
class ATM {
53+
final class ATM {
5154
private var hundred: MoneyPile
5255
private var fifty: MoneyPile
5356
private var twenty: MoneyPile
5457
private var ten: MoneyPile
55-
58+
5659
private var startPile: MoneyPile {
5760
return self.hundred
5861
}
59-
60-
init(hundred: MoneyPile,
61-
fifty: MoneyPile,
62-
twenty: MoneyPile,
62+
63+
init(hundred: MoneyPile,
64+
fifty: MoneyPile,
65+
twenty: MoneyPile,
6366
ten: MoneyPile) {
6467

6568
self.hundred = hundred
6669
self.fifty = fifty
6770
self.twenty = twenty
6871
self.ten = ten
6972
}
70-
71-
func canWithdraw(value: Int) -> String {
72-
return "Can withdraw: \(self.startPile.canWithdraw(value))"
73+
74+
func canWithdraw(amount: Int) -> String {
75+
return "Can withdraw: \(self.startPile.canWithdraw(amount: amount))"
7376
}
7477
}
7578
/*:
@@ -83,10 +86,10 @@ let hundred = MoneyPile(value: 100, quantity: 1, nextPile: fifty)
8386

8487
// Build ATM.
8588
var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten)
86-
atm.canWithdraw(310) // Cannot because ATM has only 300
87-
atm.canWithdraw(100) // Can withdraw - 1x100
88-
atm.canWithdraw(165) // Cannot withdraw because ATM doesn't has bill with value of 5
89-
atm.canWithdraw(30) // Can withdraw - 1x20, 2x10
89+
atm.canWithdraw(amount: 310) // Cannot because ATM has only 300
90+
atm.canWithdraw(amount: 100) // Can withdraw - 1x100
91+
atm.canWithdraw(amount: 165) // Cannot withdraw because ATM doesn't has bill with value of 5
92+
atm.canWithdraw(amount: 30) // Can withdraw - 1x20, 2x10
9093
/*:
9194
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Chain-Of-Responsibility)
9295
*/

source/behavioral/interpreter.swift

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,87 +7,86 @@ The interpreter pattern is used to evaluate sentences in a language.
77
### Example
88
*/
99

10-
protocol IntegerExp {
11-
func evaluate(context: IntegerContext) -> Int
12-
func replace(character: Character, integerExp: IntegerExp) -> IntegerExp
13-
func copy() -> IntegerExp
10+
protocol IntegerExpression {
11+
func evaluate(_ context: IntegerContext) -> Int
12+
func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression
13+
func copied() -> IntegerExpression
1414
}
1515

16-
class IntegerContext {
16+
final class IntegerContext {
1717
private var data: [Character:Int] = [:]
18-
18+
1919
func lookup(name: Character) -> Int {
2020
return self.data[name]!
2121
}
22-
23-
func assign(integerVarExp: IntegerVarExp, value: Int) {
24-
self.data[integerVarExp.name] = value
22+
23+
func assign(expression: IntegerVariableExpression, value: Int) {
24+
self.data[expression.name] = value
2525
}
2626
}
2727

28-
class IntegerVarExp: IntegerExp {
28+
final class IntegerVariableExpression: IntegerExpression {
2929
let name: Character
30-
30+
3131
init(name: Character) {
3232
self.name = name
3333
}
34-
35-
func evaluate(context: IntegerContext) -> Int {
36-
return context.lookup(self.name)
34+
35+
func evaluate(_ context: IntegerContext) -> Int {
36+
return context.lookup(name: self.name)
3737
}
38-
39-
func replace(name: Character, integerExp: IntegerExp) -> IntegerExp {
38+
39+
func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression {
4040
if name == self.name {
41-
return integerExp.copy()
41+
return integerExpression.copied()
4242
} else {
43-
return IntegerVarExp(name: self.name)
43+
return IntegerVariableExpression(name: self.name)
4444
}
4545
}
46-
47-
func copy() -> IntegerExp {
48-
return IntegerVarExp(name: self.name)
46+
47+
func copied() -> IntegerExpression {
48+
return IntegerVariableExpression(name: self.name)
4949
}
5050
}
5151

52-
class AddExp: IntegerExp {
53-
private var operand1: IntegerExp
54-
private var operand2: IntegerExp
55-
56-
init(op1: IntegerExp, op2: IntegerExp) {
52+
final class AddExpression: IntegerExpression {
53+
private var operand1: IntegerExpression
54+
private var operand2: IntegerExpression
55+
56+
init(op1: IntegerExpression, op2: IntegerExpression) {
5757
self.operand1 = op1
5858
self.operand2 = op2
5959
}
60-
61-
func evaluate(context: IntegerContext) -> Int {
60+
61+
func evaluate(_ context: IntegerContext) -> Int {
6262
return self.operand1.evaluate(context) + self.operand2.evaluate(context)
6363
}
64-
65-
func replace(character: Character, integerExp: IntegerExp) -> IntegerExp {
66-
return AddExp(op1: operand1.replace(character, integerExp: integerExp),
67-
op2: operand2.replace(character, integerExp: integerExp))
64+
65+
func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression {
66+
return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression),
67+
op2: operand2.replace(character: character, integerExpression: integerExpression))
6868
}
69-
70-
func copy() -> IntegerExp {
71-
return AddExp(op1: self.operand1, op2: self.operand2)
69+
70+
func copied() -> IntegerExpression {
71+
return AddExpression(op1: self.operand1, op2: self.operand2)
7272
}
7373
}
7474
/*:
7575
### Usage
7676
*/
77-
var expression: IntegerExp?
78-
var intContext = IntegerContext()
77+
var context = IntegerContext()
7978

80-
var a = IntegerVarExp(name: "A")
81-
var b = IntegerVarExp(name: "B")
82-
var c = IntegerVarExp(name: "C")
79+
var a = IntegerVariableExpression(name: "A")
80+
var b = IntegerVariableExpression(name: "B")
81+
var c = IntegerVariableExpression(name: "C")
8382

84-
expression = AddExp(op1: a, op2: AddExp(op1: b, op2: c)) // a + (b + c)
83+
var expression = AddExpression(op1: a, op2: AddExpression(op1: b, op2: c)) // a + (b + c)
8584

86-
intContext.assign(a, value: 2)
87-
intContext.assign(b, value: 1)
88-
intContext.assign(c, value: 3)
85+
context.assign(expression: a, value: 2)
86+
context.assign(expression: b, value: 1)
87+
context.assign(expression: c, value: 3)
8988

90-
var result = expression?.evaluate(intContext)
89+
var result = expression.evaluate(context)
9190
/*:
9291
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Interpreter)
9392
*/

source/behavioral/iterator.swift

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,38 @@ The iterator pattern is used to provide a standard interface for traversing a co
66

77
### Example:
88
*/
9-
struct NovellasCollection<T> {
10-
let novellas: [T]
9+
struct Novella {
10+
let name: String
1111
}
1212

13-
extension NovellasCollection: SequenceType {
14-
typealias Generator = AnyGenerator<T>
15-
16-
func generate() -> AnyGenerator<T> {
17-
var i = 0
18-
return AnyGenerator { i += 1; return i >= self.novellas.count ? nil : self.novellas[i] }
13+
struct Novellas {
14+
let novellas: [Novella]
15+
}
16+
17+
struct NovellasIterator: IteratorProtocol {
18+
19+
private var current = 0
20+
private let novellas: [Novella]
21+
22+
init(novellas: [Novella]) {
23+
self.novellas = novellas
24+
}
25+
26+
mutating func next() -> Novella? {
27+
defer { current += 1 }
28+
return novellas.count > current ? novellas[current] : nil
29+
}
30+
}
31+
32+
extension Novellas: Sequence {
33+
func makeIterator() -> NovellasIterator {
34+
return NovellasIterator(novellas: novellas)
1935
}
2036
}
2137
/*:
2238
### Usage
2339
*/
24-
let greatNovellas = NovellasCollection(novellas:["Mist"])
40+
let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] )
2541

2642
for novella in greatNovellas {
2743
print("I've read: \(novella)")

source/behavioral/mediator.swift

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,62 +6,52 @@ The mediator pattern is used to reduce coupling between classes that communicate
66

77
### Example
88
*/
9+
struct Programmer {
910

10-
class Colleague {
1111
let name: String
12-
let mediator: Mediator
13-
14-
init(name: String, mediator: Mediator) {
12+
13+
init(name: String) {
1514
self.name = name
16-
self.mediator = mediator
17-
}
18-
19-
func send(message: String) {
20-
mediator.send(message, colleague: self)
2115
}
22-
16+
2317
func receive(message: String) {
24-
assert(false, "Method should be overriden")
18+
print("\(name) received: \(message)")
2519
}
2620
}
2721

28-
protocol Mediator {
29-
func send(message: String, colleague: Colleague)
22+
protocol MessageSending {
23+
func send(message: String)
3024
}
3125

32-
class MessageMediator: Mediator {
33-
private var colleagues: [Colleague] = []
34-
35-
func addColleague(colleague: Colleague) {
36-
colleagues.append(colleague)
37-
}
38-
39-
func send(message: String, colleague: Colleague) {
40-
for c in colleagues {
41-
if c !== colleague { //for simplicity we compare object references
42-
c.receive(message)
43-
}
44-
}
26+
final class MessageMediator: MessageSending {
27+
28+
private var recipients: [Programmer] = []
29+
30+
func add(recipient: Programmer) {
31+
recipients.append(recipient)
4532
}
46-
}
4733

48-
class ConcreteColleague: Colleague {
49-
override func receive(message: String) {
50-
print("Colleague \(name) received: \(message)")
34+
func send(message: String) {
35+
for recipient in recipients {
36+
recipient.receive(message: message)
37+
}
5138
}
5239
}
53-
5440
/*:
5541
### Usage
5642
*/
43+
func spamMonster(message: String, worker: MessageSending) {
44+
worker.send(message: message)
45+
}
5746

5847
let messagesMediator = MessageMediator()
59-
let user0 = ConcreteColleague(name: "0", mediator: messagesMediator)
60-
let user1 = ConcreteColleague(name: "1", mediator: messagesMediator)
61-
messagesMediator.addColleague(user0)
62-
messagesMediator.addColleague(user1)
6348

64-
user0.send("Hello") // user1 receives message
49+
let user0 = Programmer(name: "Linus Torvalds")
50+
let user1 = Programmer(name: "Avadis 'Avie' Tevanian")
51+
messagesMediator.add(recipient: user0)
52+
messagesMediator.add(recipient: user1)
53+
54+
spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator)
6555
/*:
6656
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Mediator)
6757
*/

0 commit comments

Comments
 (0)