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