美文网首页ios底层原理
设计模式-中介者模式

设计模式-中介者模式

作者: 恍然如梦_b700 | 来源:发表于2020-06-17 16:05 被阅读0次

    中介者模式

    中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
    下面我通过代买来实现以下中介者

    
    import UIKit
    
    class ViewController: UIViewController {
    
        var fyTimer: Timer?
        var fyProxy = FYProxy()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            fyTimer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
            RunLoop.current.add(fyTimer!, forMode: .common)
        }
    
        @objc func timerFire() {
            print("timer fire")
        }
    
    }
    
    

    先来看上面代码,可能你已经发现了上面代码的问题,是的,循环引用,既然会产生循环引用,那么我们可以通过一些手段解决,比如用block回调,相信用过的都知道怎么用,这里我就不过多介绍。
    可不可以将targe转移,把一些target指向self的处理交给中介,来解决这个问题呢?
    我这里引入了一个中介者,FYProxy

    FYProxy的定义:

    import UIKit
    
    class FYProxy: NSObject {
        
        weak var target: NSObjectProtocol?
        var sel: Selector?
        var fyTimer: Timer? = nil
        
        override init() {
            super.init()
            
        }
        
        func fy_scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) {
            
            
            self.fyTimer = Timer.init(timeInterval: ti, target: self, selector: aSelector, userInfo: userInfo, repeats: yesOrNo);
            RunLoop.current.add(self.fyTimer!, forMode: .common)
            self.target = (aTarget as! NSObjectProtocol)
            self.sel = aSelector
            guard self.target?.responds(to: self.sel) == true else {
                return
            }
            
            let method = class_getInstanceMethod(self.classForCoder, #selector(self.fyTimerFire))
            class_replaceMethod(self.classForCoder, self.sel!, method_getImplementation(method!), method_getTypeEncoding(method!))
            
            
        }
        
        @objc fileprivate func fyTimerFire() {
            if let tag = self.target {
                tag.perform(self.sel)
            } else {
                self.fyTimer?.invalidate()
                self.fyTimer = nil
            }
        }
        
        //消息转发
        override func forwardingTarget(for aSelector: Selector!) -> Any? {
            if self.target?.responds(to: self.sel!) == true {
                return self.target
            } else {
                print("写这样的代码,你想上天?")
                return super.forwardingTarget(for: aSelector)
            }
        }
        
    }
    
    

    那么在VC中我们就不用这么这么使用了:

    
    import UIKit
    
    class ViewController: UIViewController {
    
        var fyTimer: Timer?
        var fyProxy = FYProxy()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //循环引用
    //        fyTimer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
    //        RunLoop.current.add(fyTimer!, forMode: .common)
            
    //        Timer.init(timeInterval: <#T##TimeInterval#>, target: <#T##Any#>, selector: <#T##Selector#>, userInfo: <#T##Any?#>, repeats: <#T##Bool#>)
            
            // Do any additional setup after loading the view.
    //        let method = NSSelectorFromString("jjjj")
            fyProxy.fy_scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
            
        }
    
        @objc func timerFire() {
            print("timer fire")
        }
        
        deinit {
            print("\(self)走了")
        }
    
    }
    
    

    你可能看着有点懵,我来解释一下上面的代码:
    FYProxy类中的target使用weak 修饰 ,这解决了循环引用的问题,
    用targer 属性记录传递的target,用sel保存外部方法,
    将外部的方法做了一个方法转换,转换为使用自己的方法
    在自己的方法中在使用targer去调用 sel,如果target销毁了,那么终止计时器相应

    此时此刻,完美,这无敌的操作。

    相关文章

      网友评论

        本文标题:设计模式-中介者模式

        本文链接:https://www.haomeiwen.com/subject/qlesxktx.html