Глобальные переменные как псевдонимы для синглетонов? - PullRequest
0 голосов
/ 26 апреля 2009

Я разрабатываю приложение Cocoa (Touch), и есть определенные данные (например, информация о собственном устройстве и список местоположений), которые я должен сохранять между различными представлениями и контроллерами.

Я думал о том, чтобы сохранить его как переменные экземпляра в моем делегате приложения, но обращение к делегату довольно громоздко (без удовольствия набирать [[[UIApplication sharedApplication] delegate] locations] каждый раз, когда я хочу получить доступ к массиву местоположений, и это много мест), поэтому я подумал о введении какого-то псевдонима (в стиле NSApp) для делегата, но за исключением NSApp, я не часто видел это в других приложениях Cocoa.

Я также подумал о том, чтобы сделать еще один шаг вперед и ввести псевдонимы для моих одноэлементных классов, поэтому вместо [State sharedState] почему бы не переименовать класс в _State и создать один его экземпляр с именем State?

Ответы [ 4 ]

1 голос
/ 29 апреля 2009

Существует несколько причин, по которым Cocoa поощряет использование [Foo sharedFoo] вместо глобального объекта Foo.

[Foo sharedFoo] может автоматически создавать экземпляр при первом использовании.

Именование экземпляра заглавной буквой очень запутанно, потому что это похоже на класс, поощряя ошибки. Последовательность в именовании лежит в основе хорошего Objective-C. Компилятор не может защитить вас от множества ошибок, потому что ObjC очень динамичен. Хорошее именование и самодисциплина в последовательности - вот что приводит к безошибочному Какао.

Параллелизм:

Foo *foo = [Foo sharedFoo];
Foo *foo = [[[Foo alloc] init] autorelease];
Foo *foo = [Bar fooAtIndex:0];

Все три из них могут быть законными в одной программе. Тот факт, что существует единственный экземпляр, не означает, что других экземпляров тоже нет. NSNotificationCenter является хорошим примером этого. Это синглтон, но вы можете создавать дополнительные экземпляры (и для этого есть причины).

Глобальная переменная может быть изменена глобально. A sharedInstance не может быть. Например, если State является глобальной переменной (а не классом), то State=nil допустимо в любой части программы. Это нарушает инкапсуляцию и является простой опечаткой для state=nil, которая не может быть перехвачена компилятором. Если State является классом, то компилятор может отловить эту простую ошибку.

Множество правил именования Какао призваны поощрять хорошо читаемый код и минимизировать ошибки в высокодинамичной и слабо типизированной среде. Как и в Perl use strict, мы должны быть очень осторожны, прежде чем отказываться от той маленькой сетки безопасности, которая у нас есть.

1 голос
/ 26 апреля 2009

Я бы, вероятно, написал класс, такой как LocationManager, который дал бы одиночный файл с [LocationManager sharedManager] или подобным. Вызов через делегата нарушает инкапсуляцию (и вы звоните через 3 объекта, чтобы туда попасть). Даже стиль NSApp #define не исправляет это.

1 голос
/ 28 апреля 2009

Основная цель использования вызова метода для получения синглтона состоит в том, чтобы его можно было лениво подготовить. Например:

static State sharedStateInstance;

@implementation State
+ (id)sharedState {
    if (!sharedStateInstance)
        sharedStateInstance = /* Allocate instance */;
    return sharedStateInstance;
}
@end

Таким образом, это означает, что если код никогда не вызывает +sharedState, ресурсы на его создание не расходуются.

Кроме того, этот код может быть улучшен в одном месте, если в будущем возникнут другие потребности, такие как обеспечение наличия одного экземпляра для потока или общего экземпляра для всех потоков (что затем потребует блокировки кода вокруг инициализации). 1007 *

0 голосов
/ 26 апреля 2009
#define FOO [[[UIApplication sharedApplication] delegate] locations] 
...