2009-10-28 5 views
2

Работа в C# и Java, я видел в основном один способ все инициализирует одиночек:Различные способы инициализации одиночек

static obj _inst = null; 

obj getInstance() { 
    if (_inst == null) { 
    _inst = new obj(); 
    } 
    return _inst; 
} 

Теперь, когда я перехожу на Objective-C для iPhone, когда я вижу примеры кода , я вижу, в основном то же самое:

static obj _inst = nil; 

+ (obj *) sharedObj { 
    if (!_inst) { 
    _inst = [[obj alloc] init]; 
    } 
    return _inst; 
} 

Там в метод класса +initialize, что называется на каждом классе в режиме исполнения Objective-C, прежде чем она используется. Есть ли какая-то причина, по которой я не мог бы использовать это для создания своих синглонов?

static obj _inst = nil; 

+ (void) initialize { 
    if (self == [obj class]) { 
    _inst = [[obj alloc] init]; 
    } 
} 

+ (obj *) sharedObj { 
    return _inst; 
} 

Это прекрасно работает, когда я пытаюсь это в моем коде, и он избавляется от проверки, чтобы увидеть, если она существует каждый раз, прежде чем он доступен. Есть ли какая-то причина, по которой я не должен создавать одиночные игры таким образом?

ответ

1

Насколько я знаю +initialize это способ сделать это. Peter Hosey предлагает несколько других уловов (внутри -init и -allocWithZone:), чтобы убедиться, что вы не можете создать экземпляр нескольких экземпляров класса. Таким образом, он становится истинным одноэлементным классом, а не просто классом с указателем на конкретный экземпляр себя внутри него.

0

Инициализация синглтона в + инициализации будет всегда выделить экземпляр. Если для экземпляра требуются значительные ресурсы (в том числе время инициализации, которое продлит время до того, как ваше приложение станет реагировать на statup), и может не использоваться, ленивый initializarion, , как в ваших примерах имеет смысл.

+0

except + initialize вызывается только в первый раз, когда доступ к классу осуществляется в любом случае. –

+0

Хорошая точка. Я стою исправлено. –

+2

Просто отметим, что есть случай (и это действительно крайний случай здесь), что + initialize можно вызвать более одного раза. Возьмем, к примеру, класс A и класс B, являющийся подклассом класса A. Класс A реализует + инициализацию, но класс B не является. Когда + initialize отправляется в класс B, поскольку он не реализует его собственный, используется его суперкласс (класс A) + initialize. И поэтому класс A + intialize вызывается более одного раза. Во всяком случае, ваш чек в + инициализировать достаточно, чтобы это не повлияло на вас. Просто поместите его там для знания и полноты. :) –

0

Lazy Инициализация полностью!

Я предпочитаю эту модель (по аналогии с тем, что у вас есть):

+ (id) sharedInstance { 
    static MyObject *sMyObject = nil; 
    if (!sMyObject) { 
     sMyObject = [[MyObject alloc] init]; 
    } 
    return sMyObject; 
} 

- (oneway void) release { 
    // no-op 
} 

Там нет необходимости ставить это в + (пустоте) инициализировать для одноточечного, так как это будет только дозвонились, когда вы первая попытка использовать класс.

+0

Я бы предпочел поместить его в метод initialize, потому что тогда мне не нужно проверять, есть ли (! SMyObject) каждый раз при доступе sharedInstance. –

+0

(! IsMyObject) - такая легкая операция, буквально инструкция cmp/jmp на CPU. Я согласен, что вы не должны одновременно называть [MyObject sharedInstance]. MyObject * obj = [MyObject sharedInstance]; [obj blah]; [obj setColor: [NSColor greenColor]]; [obj setName: @ "Hola"]; – jarjar

+1

В многопоточной среде это может привести к тому, что несколько объектов будут выделены и инициализированы, но только одна палочка. Необходимо использовать либо инициализацию + (void), либо @synchronized, чтобы защитить это.Небольшой умный метод swizzling может помочь ускорить последующие вызовы sharedInstance, чтобы избежать синхронизации и проверки. –

Смежные вопросы