使用协议实现 Swift 中间人模式

2020-07-06  本文已影响0人  csqingyang

在 OC 中, 一个比较好的组件化方案是使用 Target-Action + Mediator + runtime 实现的, 参考链接: iOS 组件化方案. 由于借助 OC 中的 runtime, 各业务模块之间不必相互持有, 只要通过 Mediator 即可实现业务调用. 简单理解为:

mediatorwithruntime.png
在 Swift 中因为没有 runtime 的加持, 能做到的是:
mediatorwithoutruntime.png

下面用一个实际例子来实现 Swift 中的 Mediator 模式.
例: 在一个团队里,有产品经理,开发工程师,质量工程师。当开发完成了某些功能,将代码提交到仓库。相关环节人员,像质量工程师和产品经理需要被通知。

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 数组, 他的主要功能是在同事间能执行发送消息的操作;
2 各同事需要持有一个中间人, 要发送消息, 就通过这个中间人去做.

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, 现在换成了 A 引用 Mediator, Mediator 引用 B. 这是语言特性造成的差异. 在开发中需要有一定的取舍.
这里还有一种做法: 使用 Notification 来实现, 但是需要注意 1 Notification 在哪个线程中 post, 就会在哪个线程 handle; 2 需要规范好 Notification 的命名和生命周期管理.

上一篇下一篇

猜你喜欢

热点阅读