iOS(Swift)常用设计模式

本文对Design Patterns implemented in Swift 1.2进了简单整理翻译。

常见的设计模式有行为模式(Behavioral)、创建模式(Creational)和结构模式(Structural)三种。

行为模式 Behavioral

在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。

维基百科

责任链模 式Chain Of Responsibility

处理命令物件或将之传到下一个可以处理的物件。

例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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(var v: Int) -> Bool {

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

var q = self.quantity

while canTakeSomeBill(v) {

if q == 0 {
break
}

v -= self.value
q -= 1
}

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

return false
}
}

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,
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))"
}
}
用法
1
2
3
4
5
6
7
8
9
10
11
12
// Create piles of money and link them together 10 < 20 < 50 < 100.**
let ten = MoneyPile(value: 10, quantity: 6, nextPile: nil)
let twenty = MoneyPile(value: 20, quantity: 2, nextPile: ten)
let fifty = MoneyPile(value: 50, quantity: 2, nextPile: twenty)
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

命令模式

在面向对象程式设计的范畴中,命令模式是一种设计模式,它尝试以物件来代表实际行动。命令物件可以把行动(action) 及其参数封装起来,于是这些行动可以被:重复多次、取消(如果该物件有实作的话)和取消后又再重做。

例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
protocol DoorCommand {
func execute() -> String
}

class OpenCommand : DoorCommand {
let doors:String

required init(doors: String) {
self.doors = doors
}

func execute() -> String {
return "Opened \(doors)"
}
}

class CloseCommand : DoorCommand {
let doors:String

required init(doors: String) {
self.doors = doors
}

func execute() -> String {
return "Closed \(doors)"
}
}

class HAL9000DoorsOperations {
let openCommand: DoorCommand
let closeCommand: DoorCommand

init(doors: String) {
self.openCommand = OpenCommand(doors:doors)
self.closeCommand = CloseCommand(doors:doors)
}

func close() -> String {
return closeCommand.execute()
}

func open() -> String {
return openCommand.execute()
}
}
用法
1
2
3
4
5
let podBayDoors = "Pod Bay Doors"
let doorModule = HAL9000DoorsOperations(doors:podBayDoors)

doorModule.open()
doorModule.close()

解释器模式

The interpreter pattern is used to evaluate sentences in a language.

例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
protocol IntegerExp {
func evaluate(context: IntegerContext) -> Int
func replace(character: Character, integerExp: IntegerExp) -> IntegerExp
func copy() -> IntegerExp
}

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
}
}

class IntegerVarExp: IntegerExp {
let name: Character

init(name: Character) {
self.name = name
}

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

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

func copy() -> IntegerExp {
return IntegerVarExp(name: self.name)
}
}

class AddExp: IntegerExp {
private var operand1: IntegerExp
private var operand2: IntegerExp

init(op1: IntegerExp, op2: IntegerExp) {
self.operand1 = op1
self.operand2 = op2
}

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 copy() -> IntegerExp {
return AddExp(op1: self.operand1, op2: self.operand2)
}
}

#####用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var expression: IntegerExp?
var intContext = IntegerContext()

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

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

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

var result = expression?.evaluate(intContext)