zoukankan      html  css  js  c++  java
  • iOS 单例

    1. 单例模式原理

    1.1. 概念

      系统中的一个类,只有一个实例,易于外界访问。

      示例:

    [[UIApplication sharedApplication] statusBarStyle];
    [NSNotificationCenter defaultCenter];
    [NSUserDefaults standardUserDefaults];
    [NSfileManager defaultManager];

    1.2. 针对解决的问题

      全局共享。

    1.3. 优缺点

      共享信息,用于管理中心。

      破坏了封装性,破坏了设计模式中的最少知识原则。

    1.4. 简单的单例

    +(instancetype)managerCenter{
         static className*center = nil;       
         if (center == nil){
             center = [[className alloc] init];   
        }      
        return center;   
    }
    

      这种方案会导致多个位置同时访问时,都会进入if逻辑里面。

      

      那么采取另外的方案:

    +(instancetype)managerCenter{
         static className*center = nil;
         static dispatch_once_t predicate;
         dispatch_once (&predicate, ^{
             center = [[className alloc] init];   
        });      
        return center;   
    }

      第三种方案:

      由于所有的类启动时都会调用+(void)initialize方法,所以,可以在里面处理:

    +(void)initialize{
        static className *center = nil;
        if(self == ([className class]){
            center = [[calssName alloc] init];
        }
    
    }    

    2. 编写严格的单例

    #import "VGPathManager.h"
    
    #pragma mark - 创建实例
    
    static VGPathManager *center = nil;
    static NSString *strClass = @"VGPathManager";
    
    @implementation VGPathManager
    
    + (instancetype)managerCenter {
        
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            
            /**
             *  这么做的原因是:在 init() 中会判断是否是本类,而不是子类
             */
            center = (VGPathManager *)strClass;
            center = [[VGPathManager alloc] init];
        });
        
        if (nil != center) {
            if (FALSE == [center cantUsedBySubClass]) {
                return nil;
            }
        }
        
        return center;
    }
    
    - (instancetype)init {
        
        NSString *string = (NSString *)center;
        if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:strClass]) {
            
            self = [super init];
            if (self) {
                if (FALSE == [self cantUsedBySubClass]) {
                    return nil;
                }
            }
            
            return self;
            
        } else {
            
            return nil;
        }
    }
    
    /**
     *  防止子类使用,如果是子类,则会是不同的名称
     */
    - (BOOL) cantUsedBySubClass {
        
        NSString *classString = NSStringFromClass([self class]);
        if ([classString isEqualToString:strClass] == NO) {
            
            return  FALSE;
        }
        
        return  TRUE;
    
    }
    
    @end
    

    2.1. 防止继承

      不允许子类也实现该实例,在请求单例的方法中的进行类的名称的判断。

    2.2. 防止多个实例

      一个类中只有一个实例,但是上面的例子并不能实现一个实例,因为还可以alloc一些实例。

    3. 例子优化存储

      用FastCoding把对象转换成NSData,然后存储到本地。 

    3.1. 用单例设计存储数据接口

      单例就不用细说了,见上面的实现。

      存储数据接口就是加上下面两个接口:

    - (void)storeValue:(id)value withKey:(NSString *)key;
    - (id) valueWithKey:(NSString *) key;

    3.2. 用单例接口隔离实现细节

    - (void)storeValue:(id)value withKey:(NSString *)key {
    
        NSParameterAssert(value);//为空则崩溃
        NSParameterAssert(key);//为空则崩溃
        
        NSData *data = [FastCoder dataWithRootObject:value];
        if (data) {
            
            [[NSUserDefaults standardUserDefaults] setObject:data forKey:key];
        }
    }
    
    - (id)valueWithKey:(NSString *)key {
    
        NSParameterAssert(key);//为空则崩溃
        
        NSData *data = [[NSUserDefaults standardUserDefaults] valueForKey:key];
        
        return [FastCoder objectWithData:data];
    }

    3.3. 在单例提供接口的寄出去进行上层封装

  • 相关阅读:
    如何利用 JConsole观察分析Java程序的运行,进行排错调优
    【解决】网站运行一段时间后就无法访问,重启Tomcat才能恢复
    不允许一个用户使用一个以上用户名与一个服务器或共享
    SVN升级到1.8后 Upgrade working copy
    Windows Server 2012 R2 创建AD域
    JTA 深度历险
    svn merge error must be ancestrally related to,trunk merge branch报错
    OutputStream-InputStream-FileOutputStream-FileInputStream-BufferedOutputStream-BufferedInputStream-四种复制方式-单层文件夹复制
    SVN提交时响应很慢,我是这样解决的。
    docker学习6-docker-compose容器集群编排
  • 原文地址:https://www.cnblogs.com/SimonGao/p/5010029.html
Copyright © 2011-2022 走看看