Здравствуйте!
— Не хотите ли войти
Tags Switch

Правильный синглтон в Objective C

15 декабря 2009

При чтении официальной документации посвященной iPhone OS, складывается впечатление что существуют всего 2 паттерна проектирования: Model View Controller и Delegate. В принципе, я согласен с таким подходом, описывать большое количество паттернов скорее вредно чем полезно, особенно для нового в какой-либо области человека. Тем не менее, я люблю пользоваться удобными и привычными подходами пусть даже и на новой платформе.

Загоревшись идеей заполучить в свое распоряжение паттерн Singleton, я немного погуглил и нашел на сайте stackoverflow.com достаточно интересную дискуссию на тему правильного синглтона для Objective C. С одной стороны, приводимые там реализации достаточно хороши, но не на столько, как хотелось бы. По большому счету, почти все «велосипедные» реализации этого паттерна на C++ имеют ту же проблему — отсутствие возможности провести деинициализацию объекта при завершении приложения. При том что Objective C имеет бесшовную состыковку с C, проблема решается достаточно просто. Можно зарегистрировать обработчик, который будет вызван при завершении работы приложения при помощи функции atexit(). Единственное что стоит не забывать при работе с функцией atexit, так это ограничение на возможное количество обработчиков — 32 штуки. За более детальной информацией можно обратиться в стандарт языка C, пункт 7.20.4.2 В результате должен получиться приблизительно следующий код:

// --- файл singleton.h --

@interface Singleton : NSObject {
}

+(Singleton*) instance;

@end
// -- файл singleton.m --

#import "Singleton.h";

@implementation Singleton

static Singleton *instance_;

static void singleton_remover() {
    [instance_ release];
}

+ (Singleton*)instance {
    @synchronized(self) {
        if( instance_ == nil ) {
            [[self alloc] init];
        }
    }

    return instance_;
}

- (id)init {
    self = [super init];
    instance_ = self;

    atexit(singleton_remover);

    return self;
}

- (void)dealloc {
    [super dealloc];
}
@end

К сожалению, в связи с отсутствием в Objective C такого понятия как шаблоны, код получается не универсальный и требует работы по принципу cut and paste, что не радует. Наверное, можно пойти по пути преобразования типов и изменить возвращаемый в instance тип на id. Но при детальном рассмотрении подобный подход мне нравится еще меньше.

Комментарии к заметке
Зарегистрируйтесь или войдите, чтобы оставить комментарий.
почему нельзя выполнить операцию singleton_remover() в теле метода dealloc? а именно через atexit() ?
olgerd
Если не использовать atexit(), метод dealloc вообще вызван не будет. А благодаря тому что в функции singleton_remover() вызывается release, объект-синглтон все же уничтожается.
+ (Store *)instance { static Store *instance; @synchronized(self) { if(!instance) { instance = [[Store alloc] init]; } } return instance; } - (id) init { self = [super init]; if (se
sakrist
блин, что-то попало, а не коммент получился, вот пример почти один в один, но немного правельнее http://pastie.org/869006.txt
sakrist
правильнее в чем? в инициализации - тоже самое, а вот деинциализации объекта, в отличие от моего варианта, не будет.
© 2009-2010, ООО «Инру»
Вход
Имя пользователя:
Пароль:
Или…
Twi
Отмена
Войти
Восстановить забытый пароль…