在 OC 中, 一個比較好的組件化方案是使用 Target-Action + Mediator + runtime 實現(xiàn)的, 參考鏈接: iOS 組件化方案. 由于借助 OC 中的 runtime, 各業(yè)務(wù)模塊之間不必相互持有, 只要通過 Mediator 即可實現(xiàn)業(yè)務(wù)調(diào)用. 簡單理解為:
mediatorwithruntime.png
在 Swift 中因為沒有 runtime 的加持, 能做到的是:
mediatorwithoutruntime.png
下面用一個實際例子來實現(xiàn) Swift 中的 Mediator 模式.
例: 在一個團隊里,有產(chǎn)品經(jīng)理宁脊,開發(fā)工程師卢肃,質(zhì)量工程師。當(dāng)開發(fā)完成了某些功能殃饿,將代碼提交到倉庫。相關(guān)環(huán)節(jié)人員,像質(zhì)量工程師和產(chǎn)品經(jīng)理需要被通知顶滩。
protocol Collogue {
var id: String { get }
func send(message: String)
func receive(message: String)
}
class Developer: Collogue {
var id: String
var qe: QE
var pm: PM
init(qe: QE, pm: PM) {
self.id = "Developer"
self.qe = qe
self.pm = pm
}
func send(message: String) {
qe.receive(message: message)
pm.receive(message: message)
}
func receive(message: String) {
print(message)
}
}
class QE: Collogue {
var id: String
var developer: Developer
var pm: PM
init(developer: Developer, pm: PM) {
self.id = "QE"
self.developer = developer
self.pm = pm
}
func send(message: String) {
developer.receive(message: message)
pm.receive(message: message)
}
func receive(message: String) {
print(message)
}
}
class PM: Collogue {
var id: String
var developer: Developer
var qe: QE
init(developer: Developer, qe: QE) {
self.id = "PM"
self.developer = developer
self.qe = qe
}
func send(message: String) {
developer.receive(message: message)
qe.receive(message: message)
}
func receive(message: String) {
print(message)
}
}
改造方法:
1 找到一個中間人取名: TeamMediator. 他能感知各位同事, 因此需要持有一個 collogues 數(shù)組, 他的主要功能是在同事間能執(zhí)行發(fā)送消息的操作;
2 各同事需要持有一個中間人, 要發(fā)送消息, 就通過這個中間人去做.
protocol Mediator {
func send(message: String, sender: Colleague)
}
class TeamMediator: Mediator {
var colleagues: [Colleague] = []
func register(colleague: Colleague) {
colleagues.append(colleague)
}
func send(message: String, sender: Colleague) {
for colleague in colleagues {
if colleague.id != sender.id {
colleague.receive(message: message)
}
}
}
}
protocol Colleague {
var id: String { get }
var mediator: Mediator { get }
func send(message: String)
func receive(message: String)
}
class Developer: Colleague {
var id: String
var mediator: Mediator
init(mediator: Mediator) {
self.id = "Developer"
self.mediator = mediator
}
func send(message: String) {
mediator.send(message: message, sender: self)
}
func receive(message: String) {
print("Developer received: " + message)
}
}
class QE: Colleague {
var id: String
var mediator: Mediator
init(mediator: Mediator) {
self.id = "QE"
self.mediator = mediator
}
func send(message: String) {
mediator.send(message: message, sender: self)
}
func receive(message: String) {
print("QE received: " + message)
}
}
class PM: Colleague {
var id: String
var mediator: Mediator
init(mediator: Mediator) {
self.id = "PM"
self.mediator = mediator
}
func send(message: String) {
mediator.send(message: message, sender: self)
}
func receive(message: String) {
print("PM received: " + message)
}
}
問題: 這里的引用耦合并沒有得到實際解決, 以前是 A 引用 B, B 引用 A, 現(xiàn)在換成了 A 引用 Mediator, Mediator 引用 B. 這是語言特性造成的差異. 在開發(fā)中需要有一定的取舍.
這里還有一種做法: 使用 Notification 來實現(xiàn), 但是需要注意 1 Notification 在哪個線程中 post, 就會在哪個線程 handle; 2 需要規(guī)范好 Notification 的命名和生命周期管理.