你這裏什麼是委託模式。您的代理人財產僅僅被稱爲class1Obj
,而不是更習慣的delegate
名稱。這裏的關鍵問題是你沒有使用協議,結果這兩個類是「緊密耦合」的,即Class2
高度依賴於實現的細節。此外,對於這兩個緊密耦合的類,目前還不清楚Class2
可能需要哪些方法Class1
。這使得維護Class1
更難,因爲很容易意外地做出改變,打破Class2
中的行爲。這也使得難以使用Class2
與Class1
以外的其他類別結合使用。
相反,您通常會聲明一個協議來精確地闡述Class2
與其他可能需要使用它的對象之間的契約性質。結果是這些類不太緊密耦合,即Class2
除了符合所討論的協議外,不需要了解其他類。此外,在編輯Class1
時,如果您聲明它符合協議,編譯器會在您未能實現某些必需的方法或屬性時發出警告。
因此,預先工作量可以忽略不計,協議使代碼更容易維護。它還提供了一些額外的靈活性,您可以在將來使用Class2
與Class1
以外的其他內容結合使用。
底線,協議可以導致代碼更容易維護,更靈活,沒有隱藏的假設。
如果你不想使用委託協議模式,另一種選擇是使用閉包,其中Class1
提供的代碼,Class2
可以調用的模塊。所以,你可以這樣做:
class Class1 {
var class2Obj = Class2()
init() {
class2Obj.handler = { [weak self] in // note `weak` reference which avoids strong reference cycle
self?.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
var handler: (() -> Void)?
func class2Method() {
handler?()
}
}
而當你有兩個類之間的豐富的接口,這種封閉模式,當你有兩個類之間的接口非常簡單的委託協議模式是有益的。
坦率地說,上述更常見的置換是關閉與Class1
在Class2
中啓動的某個特定請求更直接相關的地方。因此,您可以將參數設置爲Class2
中的適當方法。此外,你經常將數據傳遞回來,所以可想而知,我們傳遞迴一個可選String
:
class Class1 {
var class2Obj = Class2()
func performClass2Method() {
class2Obj.class2Method { string in
guard let string = string else { return }
self.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
func class2Method(completionHandler: @escaping (String?) -> Void) {
// do something which creates `string`
// when done, call the closure, passing that `string` value back
completionHandler(string)
}
}
這些閉合模型一個偉大的方式做對象之間的簡單接口外,還保持了兩類非常鬆散耦合(即Class2
對Class1
沒有依賴關係),就像在委託模式中使用協議一樣。但希望上面的關閉示例說明豐富的委託協議模式的簡單替代方案。
來源
2017-01-22 01:43:47
Rob
是的,你可以這樣溝通。但是對於其他人來說,代理,阻止和關閉更容易理解Class2通過「方法」回調。這是一個「什麼是最佳實踐」的問題:) –
@YUNCHEN - 是的,你也可以使用閉包模式,但我認爲使用閉包是最好的做法。 ,它比這更復雜,它的確依賴於在簡單的情況下,閉包可能是有用的,但是在更豐富的接口中,委託協議模式通常是優越的,它只取決於接口的性質,但是我同意,安舒的兩個緊密耦合的班級模式並不理想。 – Rob
@Rob,同意你的看法。 –