iOS避免滥用单例

作者: AKyS佐毅 | 来源:发表于2016-01-28 23:44 被阅读1906次

单例模式:

  • 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问。
  • 这个唯一的实例只能通过子类化进行扩展,而且扩展对象不会破坏客户端的代码。
  • 单例模式提供了一个为人熟知的访问点,供客户类为共享资源生成唯一实例,并通过它对共享资源进行访问。
  • 虽然静态的全局对象引用或者类方法也可以提供全局访问点,但是全局对象无法防止类被初始化一次以上,而且类方法也缺少消除耦合的灵活性。
  • 静态全局变量保持着对类的实例的唯一引用,但是当程序中有两个相同的全乎对象类型的话,就不能确保同一份共享资源的读取和输入。
  • 类方法提供了共享服务,不用创建其对象就可以访问。资源的唯一实例可以在类方法中维护。但是,当类需要被子类化以提供更好的服务时,类方法并不能解决这一问题。

使用单例模式需要注意的问题

  • 如果单例对象要由多个线程访问,那么使它线程安全是至关重要的。但我们取单例对象的时候,一般都需要检查周围加入一些@synchronized()程序块或者NSLock锁的实例。
  • "单例就是披着羊皮的全局状态"。一个单例可以被使用在任何地方,而不需要显式地声明依赖。
  • 单例应该只用来保存全局的状态,并且不能和任何作用域绑定。如果这些状态的作用域比一个完整的应用程序的生命周期要短,那么这个状态就不应该使用单例来管理。
  • 用一个单例来管理用户绑定的状态,不是很好的设计方式,需要重新评估自己的设计方案。

举例说明错误的单例使用

  • 假设现在我们创建一个单例,该单例拥有一个属性,我们姑且以MessageType来做假设.
  • messageType分为userMessage(用户消息) 和BroadcastMessage(广播消息)。
    代码块:
         #import <Foundation/Foundation.h>
         @interface MessageCenterManager : NSObject

         @property (nonatomic ,assign) NSInteger messageType;
         + (instancetype)sharedInstance;
         @end
       
        .m实现
         #import "MessageCenterManager.h"
         static MessageCenterManager *_sharedInstance;
         @implementation MessageCenterManager
         + (instancetype)sharedInstance{
              static dispatch_once_t onceToken;
             dispatch_once(&onceToken, ^{
                      _sharedInstance = [[MessageCenterManager alloc] init];
             });
             return _sharedInstance;
         }

         -(id)copyWithZone:(NSZone *)zone{
             return _sharedInstance;
         }

         +(id)allocWithZone:(struct _NSZone *)zone{
                static dispatch_once_t onceToken;
                        dispatch_once(&onceToken, ^{
                            _sharedInstance = [super allocWithZone:zone];
                         });
               return _sharedInstance;
         }
        @end

此时我们创建了一个单例,且看下边的用法,是错误的,不安全的。

       #import "UserMessage.h"
       @implementation UserMessage
       - (void)someMethod{
      //在这里是不能像这样引用单例的,这样的话用户消息和广播消息就会耦合在一起
        if([MessageCenterManager sharedInstance].messageType){
              //do something
        }else{
        }
       }
       @end

       #广播消息中
        @implementation BroadcastMessage
         - (void)someMethod{
                [[MessageCenterManager sharedInstance] setMessageType:0];
          }
        @end

重要的事情加警告

  • 这种情况应该只能发生在 BroadcastMessage显式引用了UserMessage,并表明了两者之间的关系时。这里使用了单例,由于其具有全局和多状态的特性,导致隐式地在两个看起来完全不相关的模块之间建立了耦合。

  • 二 假设现在我们需要存取用户的头像。当用户需要退出登陆的时候,我们要讲存储在本地的图片删除。

  • 当展示图片的时候需要从本地文件中读取。假设用户此时登出程序,我们需要将用户存取数据置为空,即需要将单例置为nil。

  • 因为项目中会有两个到三个地方都会有存取的操作,那么此时,单例的操作就必须注意线程安全了。

  • 其实这种将用户状态以单例形式保存所有地方都是用方式是不对的。单例应该只用来保存全局的状态,并且不能和任何作用域绑定。

  • 如果这些状态的作用域比一个完整的应用程序的生命周期要短,那么这个状态就不应该使用单例来管理。用一个单例来管理用户绑定的状态,不是一种良好的设计思维。

相关文章

  • iOS避免滥用单例

    单例模式: 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问。 这个唯一的实例只能通过子类化进行扩展,...

  • iOS 避免单例滥用

    我们似乎以前已经达成了共识,“单例模式很好用,但不能滥用”。但是在Apple和第三方Swift框架中开发人员还在大...

  • 架构(避免滥用单例)

    blog 避免滥用单例(破土君)名词:依赖注入

  • 避免单例滥用

    1、单例应该只用来保存全局的状态,并且不能和任何作用域绑定。如果这些状态的作用域比一个完整的应用程序的生命周期要短...

  • 避免滥用单例模式

    [翻译]本文翻译自objc.io官网的博客, 原文可查看Avoiding Singleton Abuse。 ———...

  • objc:Issue13——Architecture【2】

    避免单例滥用——by Stephen Poletto 单例是整个Cocoa使用的核心设计模式之一。事实上,苹果的开...

  • objc文章之避免滥用单例

    这是一篇objc上的文章,解了我很多的关于单例的困惑,原文地址 中文翻译地址 1.单例介绍 单例是Cocoa中被广...

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • 单例的使用及避免对单例的滥用

    序 单例应该只用来保存全局的状态,并且不能和任何作用域绑定。如果这些状态的作用域比一个完整的应用程序的生命周期要短...

  • 单列模式

    单例模式能够确保指定类只有一个实例,并且全局可以访问到该实例 2:避免无休止的开辟和销毁内存空间 单例也不能够滥用...

网友评论

  • nicodeng:你好 单利置为nil是将它释放了么
  • Mr_Zander:请问“用户绑定的状态”怎么理解呢?
    AKyS佐毅:@施治昂 用户的相关信息,最好不要绑定其他状态

本文标题:iOS避免滥用单例

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