个人网站整站下载,wordpress国外空间,荆州百度推广,品牌网站设计工作室单例\通知\代理 单例模式什么是单例模式#xff1f;单例模式的优缺点优点#xff1a;缺点#xff1a; 实现方式懒汉式#xff1a;饿汉式#xff1a; 通知代理总结KVO\KVC\单例模式\通知\代理\Block 单例模式
什么是单例模式#xff1f;
单例模式在整个工程中#xff0… 单例\通知\代理 单例模式什么是单例模式单例模式的优缺点优点缺点 实现方式懒汉式饿汉式 通知代理总结KVO\KVC\单例模式\通知\代理\Block 单例模式
什么是单例模式
单例模式在整个工程中相当于一个全局变量就是不论在哪里需要用到这个类的实例变量都可以通过单例方法来取得而且一旦你创建了一个单例类不论你在多少个洁面中初始化调用了这个单例方法取得对象它们所有的对象都是指向的同一块内存的存储空间即单例类保证了该类的实例对象是唯一存在的一个
单例模式的优缺点
优点
单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问从而方便对实例个数的控制并节约系统资源。单例因为类控制了实例化的过程所以类可以更加灵活的修改实例化的过程
缺点
单例对象一旦建立对象指针式保存在静态区单例对象在堆中分配的内存空间会在应用程序中止后才会被释放和静态变量相似只要进程在单例对象就在。单例类无法继承因此很难进行类的扩展。单例不适用于变化的对象如果同一类型的对象总是要在不同的用例场景发生变化单例就回引起数据的错误不能保存彼此的状态。
实现方式
懒汉式
实现原理和懒加载很想如果在程序中不适用这个对象那么就不会创建只有在你使用代码创建这个对象才会创建。这种思想在iOS开发中是很重要的也是最常见的时间换空间的做法 其实就是在第一次使用单例的时候才进行初始化
我们需要重写alloc方法这里提供了两种方法一种是alloc一种是allocWithZone方法
其实在alloc调用的底层也是allocWithZone方法所以在此我们只需要重写allocWithZone方法
id manager;(instancetype)allocWithZone:(struct _NSZone *)zone
{// 在这里判断为了优化资源防止多次加锁和判断锁if (manager nil) {// 在这里加一把锁利用本类为锁进行多线程问题的解决synchronized(self){if (manager nil) {// 调用super的allocWithZone方法来分配内存空间manager [super allocWithZone:nil];//处于历史原因OC不再使用NSZone选择直接忽略}}}return manager;
}但是这样的话还不够优化我们还可以使用GCD方法进行一个优化
首先我们来看一个GCD的API dispatch_once一次性代码只会执行一次: static dispatch_once_t onceToken;dispatch_once(onceToken, ^{//此处编写只执行一次的代码这里main默认是线程安全的});同时对manager应该使用static以避免被extern进行了操作 这里我们浅讲一下static和extern的区别 static定义在变量或函数前面它的含义是改变默认的external链接属性使它们的作用域限定在本文件内部这样其他类的文件就不能对它做引用和修改了保证了单例的一个安全性。extern修饰符extern用在变量或者函数的声明前用来说明“此变量/函数是在别处定义的要在此处引用并可以对该变量/函数进行修改” 使用GCD的单例模式添加了一个初始化单例的类方法来作为外部创建单例对象的接口
static id manager;
//自定义创建单例的类方法接口(instancetype)sharedManger{static dispatch_once_t onceToken;dispatch_once(onceToken, ^{manager [super allocWithZone:zone];});return manager;
}//但是这时候我们还是得确保安全去重写一下allocWithZone方法否则外部如果采用alloc的方法来创建单例对象的时候就会每alloc一遍就会新创建一个该对象单例就失去了意义(instancetype)allocWithZone:(struct _NSZone *)zone {if (manager nil) {manager [super allocWithZone:zone];}return manager;
}饿汉式
在使用代码去创建对象之前就已经创建好了对象。
load方法当类加载到运行环境中的时候就会调用且仅调用一次同时注意一个类只会加载一次类加载有别于引用类可以这么说所有类都会在程序启动的时候加载一次不管有没有在目前显示的视图类中引用到这个涉及到了App的启动流程initialize方法当第一次使用类的时候加载且仅加载一次
我们再来考虑
在不考虑开发者主动使用的情况下系统最多会调用一次如果父类和子类都被调用父类的调用一定在子类之前都是为了应用运行前创建合适的运行环境
在使用时都不要过重地依赖于这两个方法除非真正必要 它们的相同点在于方法只会被调用一次。
二者相比较
load 是只要类所在文件被引用就会被调用而 initialize 是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目就不会有load调用但即使类文件被引用进来但是没有使用那么 initialize 也不会被调用。
它们的相同点在于方法只会被调用一次。
所以选择load
static id manager;(void)load {//只会加载一次也就不需要加锁manager [[self alloc] init];
} (instancetype)sharedManger{if (manager nil) {manager [super allocWithZone:zone];}return. manager;
}//但是这时候我们还是得确保安全去重写一下allocWithZone方法否则外部如果采用alloc的方法来创建单例对象的时候就会每alloc一遍就会新创建一个该对象单例就失去了意义(instancetype)allocWithZone:(struct _NSZone *)zone {if (manager nil) {manager [super allocWithZone:zone];}return manager;
}通知
最熟悉的观察者模式
观察者和被观察者都无需知晓对方只需要通过标记在NSNotificationCenter中找到监听该通知所对应的类从而调用该类的方法。并且在NSNotificationCenter中观察者可以只订阅某一特定的通知并对其做出相应而不用对某一个类发的所有通知都进行更新操作。NSNotificationCenter对观察者的调用不是随机的而是遵循注册顺序一一执行的并且在该线程内是同步的。
通知的具体使用步骤
创建通知对象
NSNotification *notice [NSNotification notificationWithName:send object:self userInfo:{name:_renameTextField.text,pass:_repassTextField.text}];通知中心发送通知
[[NSNotificationCenter defaultCenter] postNotification:notice];注册通知 添加观察者来指定一个方法、名称和对象接受到通知时执行这个指定的方法。
[[NSNotificationCenter defaultCenter] addObserver:self selector:selector(recive:) name:send object:nil];接受通知后调用的方法
- (void)recive:(NSNotification *)notice {NSDictionary *dictionary notice.userInfo;_nameTextField.text dictionary[name];_passTextField.text dictionary[pass];
}总结一下通知的用法
接收通知的类注册监听者并实现接收通知的事件函数触发通知的类在适当的时候发送通知
代理
又称委托代理是iOS中常用的一种设计模式
协议是多个类共享的一个方法列表在协议中所列出的方法没有响应的实现由其它类来实现。
委托是指给一个对象提供机会对另一对象中的变化做出反应或者相应另一个对象的行为。其基本思想是协同解决问题。
从方法的定义我们不难看出委托模式能够起到两方面的作用
第一代理协助对象主体完成某项操作将需要定制化的操作通过代理来自定义实现达到和子类化对象主体同样的作用。
第二事件监听代理对象监听对象主体的某些重要事件对事件做出具体响应或广播事件交给需要作出响应的对象。 关于协议传值和属性传值
总结
KVO\KVC\单例模式\通知\代理\Block
KVO/通知 ------- 观察者模式 KVC -------- KVC模式 单例模式 代理模式
1. 代理和通知的区别
效率代理比通知高 关联delegate是强关联委托和代理双方互相知道。通知是弱关联不需要知道是谁发也不需要知道是谁接收。 代理是一对一的关系通知是一对多的关系。delegate一般是行为需要别人来完成。通知是全局通知。 代理要实现对多个类发出消息可以通过将代理者添加入集合类后遍历或通过消息转发来实现。
2. KVO和通知的区别
相同都是一对多的关系 不同通知是需要被观察者先主动发出通知观察者注册监听再响应比KVO多了发送通知这一步。 监听范围KVO是监听一个值的变化。通知不局限于监听属性的变化还可以对多种多样的状态变化进行监听监听范围广使用更灵活。 使用场景KVO的一般使用场景是监听数据变化通知是全局通知。
3. block和代理的区别
相同点block和代理都是回调的方式。使用场景相同。
不同点
block集中代码块而代理分散代码块。所以block更适用于轻便、简单的回调如网络传输。 代理适用于公共接口较多的情况这样做也更易于解耦代码架构。block运行成本高。block出栈时需要将使用的数据从栈内存拷贝到堆内存。当然如果是对象就是加计数使用完或block置为nil后才消除。 代理只是保存了一个对象指针直接回调并没有额外消耗。相对C的函数指针只是多做了一个查表动作。
4. 单例的优缺点
优点
1一个类只被实例化一次提供了对唯一实例的受控访问。 2节省系统资源 3允许可变数目的实例。
缺点
1一个类只有一个对象可能造成费任过重在一定程度上违背了“单一职费原则”。 2由于单例模式中没有抽象层因此单例类的扩展有很大的困难。 3滥用单例将带来一些负面问题如为了节省资源将数据库连接池对象设计为的单例类可能会 导致共享连接池对象的程序过多而出现连接池溢出如果实例化的对象长时间不被利用系统会认为是垃圾而被回收这将导致对象状态的丢失。