如何理解swift中的delegate

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

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID267

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章