设计模式-02-单例

完整的单例通常需要实现三个方法(GCD)


  • share方法

    + (instancetype)sharePerson
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [[self alloc] init];
        });
        return _person;
    }
    
  • alloc方法

    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [super allocWithZone:zone];
        });
        return _person;
    }
    
  • copy方法

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

通过宏实现单例(GCD方式)


  • 代码如下:

    //.h文件
    #define LYPSingletonH(name) + (instancetype)share##name;
    //.m文件
    #define LYPSingletonM(name) \
    static id _instance; \
     \
    + (instancetype)share##name \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [[self alloc] init]; \
        }); \
        return _instance; \
    } \
     \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [super allocWithZone:zone]; \
        }); \
        return _instance; \
    } \
     \
    - (id)copyWithZone:(NSZone *)zone \
    { \
        return _instance; \
    }
    
  • 注意事项

    • 每行后边的\表示下一行与该部分也是一个整体
    • .h文件下的一行要加分号,否则在引用的时候要加分号
    • 定义宏的新名字后边必须加空格,因为编译器,默认将新名字开始遇到的第一个空格前的部分作为宏的名字

通过非GCD方式实现单例


  • 实现代码如下

    static Dog *_dog;
    + (instancetype)shareDog
    {
        @synchronized(self)
        {
            if (_dog == nil)
            {
                [NSThread sleepForTimeInterval:3];
                _dog = [[self alloc] init];
            }
    
        }
        return _dog;
    }
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        @synchronized(self)
        {
            if (_dog == nil)
            {
                [NSThread sleepForTimeInterval:3];
                _dog = [super allocWithZone:zone];
            }
        }
        return _dog;
    }
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return _dog;
    }
    
  • 注意事项

    • 为创建对象是分配内存和初始化的代码加锁,若不加锁,当多个线程并发执行创建对象任务,将会破坏单例模式,创建出多个对象(通常在创建对象耗时比较长的时候发生)
      @synchronized(self) {}

注意


1.单例模式不能使用继承实现,否则所有子类创建的对象都将是第一个创建的对象

posted @ 2015-09-14 08:33  世俗孤岛  阅读(337)  评论(0编辑  收藏  举报