antonio's blog

antonio's blog


Блог о всяком разном, связанном с разработкой ПО. Пишу редко, когда есть время и желание.

antonio
Author

Share


Tags


Паттерн проектирования Singleton

antonioantonio

Паттерн проектирования Singleton (синглтон) используется когда в приложении необходимо иметь один единственный экземпляр класса. В Cocoa данный паттерн проектирования используется довольно часто. Например, классы NSApplication, NSExceptionHandler NSUserDefaults являются синглтонами. Создать свой класс синглтон не составляет труда. Для этого необходимо перекрыть методы относящиеся к управлению памятью и реализовать метод, который создает и возвращает экземпляр класса. Создание экземпляра должно быть выполнено один раз. Рассмотрим синглтона на примере.

Создадим класс Counter

@interface Counter : NSObject {
    @private 
    NSInteger _count;
}
@property NSInteger count;
+ (Counter *)sharedInstance;
@end
@implementation Counter 
@synthesize count = _count;
+(Counter *) sharedInstance {
    static Counter *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_sharedInstance == nil){
            _sharedInstance = [[super allocWithZone:NULL] init];
        }
    });
    return _sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
    return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
    return self;
}
- (id)retain {
    return self;
}
- (NSUInteger)retainCount {
    return NSUIntegerMax;
}
- (oneway void)release {
}
- (id)autorelease {
    return self;
}

@end

Первое, что мы сделали - это создали статический метод sharedInstance:, возвращающий наш единственный экземпляр. В методе объявлена статическая переменная, хранящая экземпляр, между вызовами метода. Далее в методе проверяется, был ли создан экземпляр ранее, если экземпляр был создан ранее, то возвращаем его, иначе создаем экземпляр и создаем и возвращаем его.

Экземпляр создается с помощью функции dispatch_once(). Функция обеспечивает потокобезопасность выполнения блока кода и гарантирует, что этот блок будет выполнен один раз за все время работы приложения.

Функция dispatch_once() первым аргументом принимает предикат, вторым блок кода. Предикат используется для того, чтобы проверить выполнялся ли блок кода ранее.

Для того чтобы пользователи могли непосредственно создавать и инициализировать экземпляр нашего класса, мы переопределили метод allocWithZone: - метод возвращает статический экземпляр.

Также мы переопределили методы retain:, retainCount:, release: и autorelease: для предотвращения уничтожения нашего экземпляра.

Пример использования:

Counter *counter = [Counter sharedInstance];  
couner.count++;

NSLog(@"%ld",  [[Counter sharedInstance] count]); // выведет 1

Counter *counter2 = [Counter alloc] init];  
counter2.count++;

NSLog(@"%ld",  [counter2 count]); // выведет 2  
antonio
Author

antonio

Comments