Skip to content

Commit

Permalink
Behavioral Patterns updated to Swift2.
Browse files Browse the repository at this point in the history
  • Loading branch information
ochococo committed Nov 21, 2016
1 parent 51546fd commit 3f2de97
Show file tree
Hide file tree
Showing 11 changed files with 414 additions and 358 deletions.

Large diffs are not rendered by default.

57 changes: 30 additions & 27 deletions source/behavioral/chain_of_responsibility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,73 @@ The chain of responsibility pattern is used to process varied requests, each of

### Example:
*/
class MoneyPile {
final class MoneyPile {

let value: Int
var quantity: Int
var nextPile: MoneyPile?

init(value: Int, quantity: Int, nextPile: MoneyPile?) {
self.value = value
self.quantity = quantity
self.nextPile = nextPile
}

func canWithdraw(v: Int) -> Bool {

var v = v
func canWithdraw(amount: Int) -> Bool {

var amount = amount

func canTakeSomeBill(want: Int) -> Bool {
return (want / self.value) > 0
}

var q = self.quantity

while canTakeSomeBill(v) {
var quantity = self.quantity

if q == 0 {
while canTakeSomeBill(want: amount) {

if quantity == 0 {
break
}

v -= self.value
q -= 1
amount -= self.value
quantity -= 1
}

if v == 0 {
guard amount > 0 else {
return true
} else if let next = self.nextPile {
return next.canWithdraw(v)
}

if let next = self.nextPile {
return next.canWithdraw(amount: amount)
}

return false
}
}

class ATM {
final class ATM {
private var hundred: MoneyPile
private var fifty: MoneyPile
private var twenty: MoneyPile
private var ten: MoneyPile

private var startPile: MoneyPile {
return self.hundred
}
init(hundred: MoneyPile,
fifty: MoneyPile,
twenty: MoneyPile,

init(hundred: MoneyPile,
fifty: MoneyPile,
twenty: MoneyPile,
ten: MoneyPile) {

self.hundred = hundred
self.fifty = fifty
self.twenty = twenty
self.ten = ten
}
func canWithdraw(value: Int) -> String {
return "Can withdraw: \(self.startPile.canWithdraw(value))"

func canWithdraw(amount: Int) -> String {
return "Can withdraw: \(self.startPile.canWithdraw(amount: amount))"
}
}
/*:
Expand All @@ -83,10 +86,10 @@ let hundred = MoneyPile(value: 100, quantity: 1, nextPile: fifty)

// Build ATM.
var atm = ATM(hundred: hundred, fifty: fifty, twenty: twenty, ten: ten)
atm.canWithdraw(310) // Cannot because ATM has only 300
atm.canWithdraw(100) // Can withdraw - 1x100
atm.canWithdraw(165) // Cannot withdraw because ATM doesn't has bill with value of 5
atm.canWithdraw(30) // Can withdraw - 1x20, 2x10
atm.canWithdraw(amount: 310) // Cannot because ATM has only 300
atm.canWithdraw(amount: 100) // Can withdraw - 1x100
atm.canWithdraw(amount: 165) // Cannot withdraw because ATM doesn't has bill with value of 5
atm.canWithdraw(amount: 30) // Can withdraw - 1x20, 2x10
/*:
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Chain-Of-Responsibility)
*/
89 changes: 44 additions & 45 deletions source/behavioral/interpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,87 +7,86 @@ The interpreter pattern is used to evaluate sentences in a language.
### Example
*/

protocol IntegerExp {
func evaluate(context: IntegerContext) -> Int
func replace(character: Character, integerExp: IntegerExp) -> IntegerExp
func copy() -> IntegerExp
protocol IntegerExpression {
func evaluate(_ context: IntegerContext) -> Int
func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression
func copied() -> IntegerExpression
}

class IntegerContext {
final class IntegerContext {
private var data: [Character:Int] = [:]

func lookup(name: Character) -> Int {
return self.data[name]!
}
func assign(integerVarExp: IntegerVarExp, value: Int) {
self.data[integerVarExp.name] = value

func assign(expression: IntegerVariableExpression, value: Int) {
self.data[expression.name] = value
}
}

class IntegerVarExp: IntegerExp {
final class IntegerVariableExpression: IntegerExpression {
let name: Character

init(name: Character) {
self.name = name
}
func evaluate(context: IntegerContext) -> Int {
return context.lookup(self.name)

func evaluate(_ context: IntegerContext) -> Int {
return context.lookup(name: self.name)
}
func replace(name: Character, integerExp: IntegerExp) -> IntegerExp {

func replace(character name: Character, integerExpression: IntegerExpression) -> IntegerExpression {
if name == self.name {
return integerExp.copy()
return integerExpression.copied()
} else {
return IntegerVarExp(name: self.name)
return IntegerVariableExpression(name: self.name)
}
}
func copy() -> IntegerExp {
return IntegerVarExp(name: self.name)

func copied() -> IntegerExpression {
return IntegerVariableExpression(name: self.name)
}
}

class AddExp: IntegerExp {
private var operand1: IntegerExp
private var operand2: IntegerExp
init(op1: IntegerExp, op2: IntegerExp) {
final class AddExpression: IntegerExpression {
private var operand1: IntegerExpression
private var operand2: IntegerExpression

init(op1: IntegerExpression, op2: IntegerExpression) {
self.operand1 = op1
self.operand2 = op2
}
func evaluate(context: IntegerContext) -> Int {

func evaluate(_ context: IntegerContext) -> Int {
return self.operand1.evaluate(context) + self.operand2.evaluate(context)
}
func replace(character: Character, integerExp: IntegerExp) -> IntegerExp {
return AddExp(op1: operand1.replace(character, integerExp: integerExp),
op2: operand2.replace(character, integerExp: integerExp))

func replace(character: Character, integerExpression: IntegerExpression) -> IntegerExpression {
return AddExpression(op1: operand1.replace(character: character, integerExpression: integerExpression),
op2: operand2.replace(character: character, integerExpression: integerExpression))
}
func copy() -> IntegerExp {
return AddExp(op1: self.operand1, op2: self.operand2)

func copied() -> IntegerExpression {
return AddExpression(op1: self.operand1, op2: self.operand2)
}
}
/*:
### Usage
*/
var expression: IntegerExp?
var intContext = IntegerContext()
var context = IntegerContext()

var a = IntegerVarExp(name: "A")
var b = IntegerVarExp(name: "B")
var c = IntegerVarExp(name: "C")
var a = IntegerVariableExpression(name: "A")
var b = IntegerVariableExpression(name: "B")
var c = IntegerVariableExpression(name: "C")

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

intContext.assign(a, value: 2)
intContext.assign(b, value: 1)
intContext.assign(c, value: 3)
context.assign(expression: a, value: 2)
context.assign(expression: b, value: 1)
context.assign(expression: c, value: 3)

var result = expression?.evaluate(intContext)
var result = expression.evaluate(context)
/*:
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Interpreter)
*/
34 changes: 25 additions & 9 deletions source/behavioral/iterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,38 @@ The iterator pattern is used to provide a standard interface for traversing a co

### Example:
*/
struct NovellasCollection<T> {
let novellas: [T]
struct Novella {
let name: String
}

extension NovellasCollection: SequenceType {
typealias Generator = AnyGenerator<T>

func generate() -> AnyGenerator<T> {
var i = 0
return AnyGenerator { i += 1; return i >= self.novellas.count ? nil : self.novellas[i] }
struct Novellas {
let novellas: [Novella]
}

struct NovellasIterator: IteratorProtocol {

private var current = 0
private let novellas: [Novella]

init(novellas: [Novella]) {
self.novellas = novellas
}

mutating func next() -> Novella? {
defer { current += 1 }
return novellas.count > current ? novellas[current] : nil
}
}

extension Novellas: Sequence {
func makeIterator() -> NovellasIterator {
return NovellasIterator(novellas: novellas)
}
}
/*:
### Usage
*/
let greatNovellas = NovellasCollection(novellas:["Mist"])
let greatNovellas = Novellas(novellas: [Novella(name: "The Mist")] )

for novella in greatNovellas {
print("I've read: \(novella)")
Expand Down
62 changes: 26 additions & 36 deletions source/behavioral/mediator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,52 @@ The mediator pattern is used to reduce coupling between classes that communicate

### Example
*/
struct Programmer {

class Colleague {
let name: String
let mediator: Mediator

init(name: String, mediator: Mediator) {

init(name: String) {
self.name = name
self.mediator = mediator
}

func send(message: String) {
mediator.send(message, colleague: self)
}

func receive(message: String) {
assert(false, "Method should be overriden")
print("\(name) received: \(message)")
}
}

protocol Mediator {
func send(message: String, colleague: Colleague)
protocol MessageSending {
func send(message: String)
}

class MessageMediator: Mediator {
private var colleagues: [Colleague] = []

func addColleague(colleague: Colleague) {
colleagues.append(colleague)
}

func send(message: String, colleague: Colleague) {
for c in colleagues {
if c !== colleague { //for simplicity we compare object references
c.receive(message)
}
}
final class MessageMediator: MessageSending {

private var recipients: [Programmer] = []

func add(recipient: Programmer) {
recipients.append(recipient)
}
}

class ConcreteColleague: Colleague {
override func receive(message: String) {
print("Colleague \(name) received: \(message)")
func send(message: String) {
for recipient in recipients {
recipient.receive(message: message)
}
}
}

/*:
### Usage
*/
func spamMonster(message: String, worker: MessageSending) {
worker.send(message: message)
}

let messagesMediator = MessageMediator()
let user0 = ConcreteColleague(name: "0", mediator: messagesMediator)
let user1 = ConcreteColleague(name: "1", mediator: messagesMediator)
messagesMediator.addColleague(user0)
messagesMediator.addColleague(user1)

user0.send("Hello") // user1 receives message
let user0 = Programmer(name: "Linus Torvalds")
let user1 = Programmer(name: "Avadis 'Avie' Tevanian")
messagesMediator.add(recipient: user0)
messagesMediator.add(recipient: user1)

spamMonster(message: "I'd Like to Add you to My Professional Network", worker: messagesMediator)
/*:
>**Further Examples:** [Design Patterns in Swift](https://github.com/kingreza/Swift-Mediator)
*/
Loading

0 comments on commit 3f2de97

Please sign in to comment.