美文网首页
单例模式

单例模式

作者: himyfairy | 来源:发表于2016-04-11 22:51 被阅读190次

    1.单例模式(Singleton)基本概念

    • 什么是单例模式
      • 单例模式即一个类的对象为唯一的一个实例对象,内存地址相同

    2.单例模式的简单实现

    • 自定义QLPlayer类,使其成为单例
      • 遵守苹果的规范,单例一般会提供sharedXXX或者defaultXXX方法
      • 为实现copymutableCopy方法,遵守NSCopyingNSMutableCopying协议
    #import <Foundation/Foundation.h>
    @interface QLPlayer : NSObject <NSCopying, NSMutableCopying>
    + (instancetype)sharedPlayer;
    @end
    
    • 类的实现
    • 因为alloc方法内部会调用allocWithZone,故重写allocWithZone方法实现单例
    • 调用dispatch_once函数,保证了在多线程同时调用的情况下,依然返回单例对象
    
    #import "QLPlayer.h"
    @implementation QLPlayer
    + (instancetype)sharedPlayer
    {
        QLPlayer *instance = [[self alloc] init];
        return instance;
    }
    
    static QLPlayer *_instance = nil;
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init];
        });
        return _instance;
    }
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    
    - (id)mutableCopyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    

    验证

    • 用五种不同的方法创建QLPlayer对象,打印对象内存地址
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        QLPlayer *player1 = [QLPlayer sharedPlayer];
        QLPlayer *player2 = [[QLPlayer alloc] init];
        QLPlayer *player3 = [QLPlayer new];
        QLPlayer *player4 = [player1 copy];
        QLPlayer *player5 = [player1 mutableCopy];
        
        NSLog(@"%p, %p, %p, %p, %p", player1, player2, player3, player4, player5);
    }
    @end
    
    • 结果如下,内存地址相同,说明是单例对象!


    3.单例模式宏抽取

    • interfaceSingleton(Name)来代替自定义单例对象类方法的声明
    #define interfaceSingleton(Name) +(instancetype)shared##Name
    
    • implementationSingleton(Name)来代替自定义单例对象类方法的实现
    #define implementationSingleton(Name) \
    + (instancetype)shared##Name \
    { \
        Name *instance = [[self alloc] init]; \
        return instance; \
    } \
    static Name *_instance = nil; \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [[super allocWithZone:zone] init]; \
        }); \
        return _instance; \
    } \
    - (id)copyWithZone:(NSZone *)zone \
    { \
        return _instance; \
    } \
    - (id)mutableCopyWithZone:(NSZone *)zone \
    { \
        return _instance; \
    }
    

    注意:如果是在MRC中,还需实现以下方法:

    - (instancetype)retain
    {
        return _player;
    }
    
    - (oneway void)release
    {
        //为了保证只有一个实例对象,这里do nothing
    }
    
    - (NSUInteger)retainCount
    {
        return MAXFLOAT; //表示这是个单例对象
    }
    

    相应的,抽取的宏中,方法的声明部分不许改变,方法的实现部分,需改为:

    #if __has_feature(objc_arc)
    
    // 说明是ARC模式
    #define implementationSingleton(Name) \
    + (instancetype)shared##Name \
    { \
    Name *instance = [[self alloc] init]; \
    return instance; \
    } \
    static Name *_instance = nil; \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
    _instance = [[super allocWithZone:zone] init]; \
    }); \
    return _instance; \
    } \
    - (id)copyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    } \
    - (id)mutableCopyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    }
    
    #else
    // 说明是MRC模式
    #define implementationSingleton(Name) \
    + (instancetype)shared##Name \
    { \
    Name *instance = [[self alloc] init]; \
    return instance; \
    } \
    static Name *_instance = nil; \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
    _instance = [[super allocWithZone:zone] init]; \
    }); \
    return _instance; \
    } \
    - (id)copyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    } \
    - (id)mutableCopyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    } \
    - (instancetype)retain \
    { \
        return _player; \
    } \
    - (oneway void)release \
    { \
    } \
    - (NSUInteger)retainCount \
    { \
        return MAXFLOAT; \
    }
    
    #endif
    

    验证

    • 自定义QLCar类,.h.m文件如下
    #import <Foundation/Foundation.h>
    #import "QLSingleton.h"
    @interface QLCar : NSObject
    interfaceSingleton(QLCar);
    @end
    
    #import "QLCar.h"
    @implementation QLCar
    implementationSingleton(QLCar)
    @end
    
    • 用五种不同的方法创建QLCar对象,打印对象内存地址
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        QLCar *car1 = [QLCar sharedQLCar];
        QLCar *car2 = [[QLCar alloc] init];
        QLCar *car3 = [QLCar new];
        QLCar *car4 = [car1 copy];
        QLCar *car5 = [car1 mutableCopy];
        
        NSLog(@"%p, %p, %p, %p, %p", car1, car2, car3, car4, car5);
    }
    @end
    
    • 结果如下,内存地址相同,说明是单例对象!


    相关文章

      网友评论

          本文标题:单例模式

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