Menu
CoddyTech

Pola Delegasi

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Swift di Coddy. Pelajaran 46 dari 57.

Delegasi memungkinkan sebuah object menyerahkan beberapa keputusan kepada object lain, yaitu delegate-nya, melalui sebuah protokol. Object tersebut menjalankan tugasnya dan bertanya kepada delegate pada bagian-bagian yang bervariasi. Framework Apple menggunakan pola ini di mana-mana:

protocol DownloadDelegate: AnyObject {
    func progress(_ percent: Int)
    func finished(_ file: String)
}

final class Downloader {
    weak var delegate: DownloadDelegate?

    func download(_ file: String) {
        for p in [50, 100] { delegate?.progress(p) }
        delegate?.finished(file)
    }
}

final class Screen: DownloadDelegate {
    func progress(_ percent: Int) { print("\(percent)%") }
    func finished(_ file: String) { print("done: \(file)") }
}

let screen = Screen()
let d = Downloader()
d.delegate = screen
d.download("photo.png")

Output:

50%
100%
done: photo.png

property delegate bersifat opsional dan pemanggilannya menggunakan delegate?., jadi object tetap berfungsi meskipun tidak ada yang mendengarkan. Deklarasinya menggunakan weak agar object tidak membuat delegate tetap hidup dengan sendirinya, sehingga siklus retain antara object yang saling menunjuk dapat dihindari:

weak var delegate: DownloadDelegate?   // mengharuskan protokol hanya untuk class: AnyObject
delegate?.finished(file)               // tidak melakukan apa pun jika tidak ada delegate

Sebuah delegate juga dapat menjawab pertanyaan, sehingga delegate dapat menyesuaikan perilaku object tanpa membuat subclass:

protocol ListDelegate: AnyObject {
    func shouldShow(_ item: String) -> Bool
}

final class ListView {
    weak var delegate: ListDelegate?
    func render(_ items: [String]) -> [String] {
        items.filter { delegate?.shouldShow($0) ?? true }
    }
}

final class HideDrafts: ListDelegate {
    func shouldShow(_ item: String) -> Bool { !item.hasPrefix("draft") }
}

let view = ListView()
let rules = HideDrafts()
print(view.render(["a", "draft b"]))
view.delegate = rules
print(view.render(["a", "draft b"]))

Output:

["a", "draft b"]
["a"]

Delegasi berbeda dari pola observer: sebuah object memiliki satu delegate yang ditanyai dan diberi tahu, sedangkan sebuah subject dapat memiliki banyak observer yang hanya diberi tahu.

// delegasi: satu mitra, dapat menjawab pertanyaan
weak var delegate: TableDelegate?
// pengamat: pendengar dalam jumlah berapa pun, hanya menerima pemberitahuan
private var observers: [(Event) -> Void] = []
challenge icon

Tantangan

Mudah

Checkout meminta keputusan dari delegatenya. Protokol CheckoutDelegate (khusus class) memiliki discount(for total: Int) -> Int dan didComplete(total: Int). Checkout memiliki weak var delegate, dan pay(_ prices: [Int]) -> Int menjumlahkan harga, mengurangi diskon delegate (0 jika tidak ada delegate), memberi tahu delegate total akhir, lalu mengembalikannya. Implementasikan LoyaltyShop, sebuah delegate yang memberikan diskon 10% untuk total 100 atau lebih dan mencatat setiap total yang selesai di receipts.

Kode yang disediakan membaca baris berisi harga yang dipisahkan koma. Kode ini memproses pembayaran pada baris pertama tanpa delegate dan baris lainnya dengan LoyaltyShop, mencetak setiap total, lalu mencetak receipts: 120 90.

Letakkan kodemu di CheckoutDelegate.swift, Checkout.swift, dan LoyaltyShop.swift. main.swift berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

// Kode input/output yang disediakan: biarkan tetap seperti ini
var input: [String] = []
while let line = readLine() { input.append(line) }
let checkout = Checkout()
let shop = LoyaltyShop()
for (i, line) in input.enumerated() {
    if i == 1 { checkout.delegate = shop }
    print(checkout.pay(line.split(separator: ",").map { Int($0)! }))
}
print("receipts: " + shop.receipts.map { String($0) }.joined(separator: " "))
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Playground Swift