Delegation翻译为代理或者委托,是一种设计模式。顾名思义,使class或struct能够将某些职责移交给其他类型的实例。
该设计模式通过定义一个封装(包含)delegate的protocol(协议)来实现,从而保证这个代理囊括所定义的功能。Delegation可用于响应特定操作,或者从外部源检索数据,而不需要知道该源的基础类型。
(一)这里举一个dice-based(摇骰子)的游戏作为例子:
定义两个protocol:
DiceGame:被所有需要骰子的游戏采用;
DiceGameDelegate:被所有需要track(跟踪)游戏过程的类型所采用;
protocol DiceGame {
var dice: Dice { get }
func play()
}
protocol DiceGameDelegate {
func gameDidStart(_ game: DiceGame)
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(_ game: DiceGame)
}
(二)这里有一个Snakes and Ladders(蛇与梯子)的游戏,使用了筛子所以采用DiceGame协议(protocol),并且设置了一个DiceGameDelegate的代理来track游戏的过程。想具体了解Snakes and ladders这个游戏过程的可以参考[Control flow 中的break]。(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID137)
class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
init() {
board = Array(repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDidEnd(self)
}
}
(三)
class DiceGameTracker: DiceGameDelegate {
var numberOfTurns = 0
func gameDidStart(_ game: DiceGame) {
numberOfTurns = 0
if game is SnakesAndLadders {
print("Started a new game of Snakes and Ladders")
}
print("The game is using a \(game.dice.sides)-sided dice")
}
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
numberOfTurns += 1
print("Rolled a \(diceRoll)")
}
func gameDidEnd(_ game: DiceGame) {
print("The game lasted for \(numberOfTurns) turns")
}
}
DiceGameTracker实现了所有DiceGameDelegate中所要求的三个方法,从而达到记录整个游戏过程的目的。
(四)下面是整个游戏实际运行的过程:
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
// Started a new game of Snakes and Ladders
// The game is using a 6-sided dice
// Rolled a 3
// Rolled a 5
// Rolled a 4
// Rolled a 5
// The game lasted for 4 turns
分别定义了一个实现DiceGameDelegate的tracker和一个游戏game,将game的代理设置为tracker,当game调用play函数的时候,track会代理地记录下游戏的整个过程。
参考:
The swift programming language