2009-10-28 4 views
2

de travail en C# et Java, j'ai vu au fond d'une façon tout le monde initialise singletons:différentes façons d'initialiser singletons

static obj _inst = null; 

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

Maintenant, quand je passe à Objective-C pour l'iPhone, chaque fois que je vois des exemples de code , je vois essentiellement la même chose:

static obj _inst = nil; 

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

il y a une méthode de classe +initialize qui est appelée à chaque classe dans l'exécution Objective-C avant qu'il ne soit utilisé. Y a-t-il une raison pour laquelle je ne pourrais pas l'utiliser pour créer mes singletons?

static obj _inst = nil; 

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

+ (obj *) sharedObj { 
    return _inst; 
} 

Il fonctionne très bien quand je l'essayer dans mon code, et il se débarrasse de vérifier pour voir si elle existe à chaque fois avant qu'il ne soit accessible. Y a-t-il une raison pour laquelle je ne devrais pas créer des singletons de cette façon?

Répondre

1

En ce qui me concerne +initialize est le moyen de le faire. Peter Hosey suggère un couple d'autres captures (à l'intérieur -init et -allocWithZone:) pour vous assurer que vous ne pouvez pas instancier plus d'une instance de la classe, jamais. Cela en fait une véritable classe singleton et pas seulement une classe avec un pointeur sur une instance particulière de lui-même.

0

Initialiser le singleton dans + initialiser toujours allouer l'instance. Si l'instance nécessite des ressources significatives (y compris le temps d'initialisation qui prolongera le délai avant que votre application ne réagisse à statup) et ne puisse être utilisée, l'initialisation paresseuse, comme dans vos exemples est logique.

+0

sauf que + initialize n'est appelée que la première fois que la classe est accédée. –

+0

Bon point. Je me suis trompé. –

+2

Juste pour souligner qu'il y a un cas (et c'est vraiment un cas de bord ici) que + initialize peut être appelé plus d'une fois. Prenez l'exemple de la classe A et de la classe B étant une sous-classe de la classe A. La classe A implémente + initialise, mais pas la classe B. Lorsque l'initialisation + est envoyée à la classe B, parce qu'elle n'implémente pas la sienne, l'implémentation de + l'initialisation de la super-classe (classe A) est utilisée. Et donc + l'intialize de classe A a été appelé plus d'une fois. Quoi qu'il en soit, votre enregistrement + initialisation est suffisant pour que cela ne vous affecte plus. Juste le mettre là pour la connaissance et l'exhaustivité. :) –

0

Initialisation paresseuse jusqu'au bout!

Je préfère ce modèle (semblable à ce que vous avez):

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

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

Il n'y a pas besoin de mettre cela en + (void) initialize pour un singleton, car il ne s'appelé lorsque vous première tentative d'utilisation de la classe.

+0

Je préférerais le mettre dans la méthode initialize, parce que je n'ai pas besoin de vérifier if (! SMyObject) à chaque fois que l'on part de sharedInstance. –

+0

Le (! IsMyObject) est une opération si légère, littéralement une instruction cmp/jmp sur la CPU. Je suis d'accord que vous ne devriez pas appeler [MyObject sharedInstance] à chaque fois. MyObject * obj = [MyObject sharedInstance]; [obj blah]; [obj setColor: [NSColor greenColor]]; [obj setName: @ "Hola"]; – jarjar

+1

Dans un environnement multithread, cela peut entraîner l'allocation et l'initialisation de plusieurs objets, mais un seul reste. Soit l'initialisation + (void) doit être utilisée, soit un @synchronized doit le protéger.Une petite méthode astucieuse peut aider à accélérer les futurs appels de SharedInstance pour éviter la synchronisation et la vérification. –

Questions connexes