使用協(xié)議實現(xiàn) Swift 中間人模式

在 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 的命名和生命周期管理.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叶洞,一起剝皮案震驚了整個濱河市鲫凶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌京办,老刑警劉巖掀序,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惭婿,居然都是意外死亡不恭,警方通過查閱死者的電腦和手機叶雹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來换吧,“玉大人折晦,你說我怎么就攤上這事≌赐撸” “怎么了满着?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贯莺。 經(jīng)常有香客問我风喇,道長,這世上最難降的妖魔是什么缕探? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任魂莫,我火速辦了婚禮,結(jié)果婚禮上爹耗,老公的妹妹穿的比我還像新娘耙考。我一直安慰自己,他們只是感情好潭兽,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布倦始。 她就那樣靜靜地躺著,像睡著了一般山卦。 火紅的嫁衣襯著肌膚如雪鞋邑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天怒坯,我揣著相機與錄音炫狱,去河邊找鬼。 笑死剔猿,一個胖子當(dāng)著我的面吹牛视译,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播归敬,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酷含,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汪茧?” 一聲冷哼從身側(cè)響起椅亚,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舱污,沒想到半個月后呀舔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡扩灯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年媚赖,在試婚紗的時候發(fā)現(xiàn)自己被綠了霜瘪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡惧磺,死狀恐怖颖对,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磨隘,我是刑警寧澤缤底,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站番捂,受9級特大地震影響个唧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜白嘁,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一坑鱼、第九天 我趴在偏房一處隱蔽的房頂上張望膘流。 院中可真熱鬧絮缅,春花似錦、人聲如沸呼股。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彭谁。三九已至吸奴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缠局,已是汗流浹背则奥。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狭园,地道東北人读处。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像唱矛,于是被迫代替她去往敵國和親罚舱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355