设计模式学习

观察者模式

kvo机制是观察者模式的具体实现,kvo就是键值观察机制,一个对象可以注册为另一个对象的观察者来检测对方的属性的变化并作出响应操作。

纯swift其实没有这个 玩意,因为这东西是oc的,swift要想使用kvo/kvc的话就必须继承自NSobject暴露给oc,所以swift的结构体和枚举就用不了(因为无法继承)。

虽然有局限性,但是有时候真的能够带来方便。比如说,在某些情况下,一个属性的值取决于另一个对象中的一个或者多个属性值时候,利用KVO的特效就相当的方便了。

使用KVO的基本步骤是:

  1. 调用addObserver(_ observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?)
  2. 重写函数 observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
  3. 在不需要观察属性的时候移除removeObserver(_ observer: NSObject, forKeyPath keyPath: String)
  4. 如果观察者被多次移除,程序崩溃
  5. 多次添加观察者,程序崩溃
  6. 观察者被deinit了,但没有移除监听,程序崩溃

引用:

KVO是通过一种叫isa-swizzling技术实现的。什么是isa-swizzling呢?顾名思义,isa指针指向维护调度表的对象类,调度表基本包含了指向该类的实现方法的指针,以及其他数据。当观察者注册对象的属性时,观察对象的isa指针被修改,指向中间类而不是真正的类。通俗的讲,每个类对象都有一个isa指针,该指针指向当前类,当这个类对象的属性被观察时,系统会动态生成一个中间类(派生类),然后把这个isa指针指向这个中间类,在这个中间类重写被观察属性的setter方法,在这个中间类重写的setter方法实现真正的通知机制。这个通知机制又使用了willChangeValueForKey(Swift中willChangeValue(forKey key: String))和didChangeValueForKey(Swift中didChangeValue(forKey key: String))这两个方法。

优点:

缺点:

代理模式

一个对象A想要实现某些功能,但是不想自己做,另一个类B刚好可以实现这个功能。所以A(老板)可以定义个delegate属性,请B来做,但是B来做的前提是遵循某个协议。举例:

女人有个gohome回家方法。但是女人不会开车,就设置一个代理,让这个代理来drive()

class women: human{
    var delegate:drivedelegate?
    
    init(delegate:drivedelegate) {
        self.delegate = delegate
    }
    func shopping(){
        print("购物")
    }
    
    func gohome(){
        guard delegate != nil else {
            return
        }
        delegate?.drive()
    }
}

protocol drivedelegate {
    func drive()
}

class man:human,drivedelegate{
    func drive(){
        print("开车")
    }
}

直接将delegate用弱引用修饰会报错因为weak与弱引用计数有关,只能修饰对象,不能修饰协议限制的any。

解决:

protocol drivedelegate:class{
    func drive()
}//加个class
@objc protocol drivedelegate{
    func drive()
}
protocol drivedelegate:NSObjectProtocol{
    func drive()
}

优点:职责清晰,易扩展

缺点:只能一对一

单例模式

一个对象在整个生命周期中只实现一个实例,例如创建一个类,类里面有个属性的类型是当前这个类,并且他是一个static或者class修饰的类型属性,然后这个类的构造方法还是private私有的,这样就可以实现一个单例类。

class danli{
    static let standard:danli = danli(name: "fmy")
    
    var name:String
    
    private init(name:String){
        self.name = name
    }
}

danli.standard.name = "666"

优点:易于定位

缺点:

1.不利于扩展.

2.由于单例类在运行过程中一直占用内存资源,在闲置的时候并不会被销毁,所以闲置时也消耗了内存资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值