Question

Diriez-vous cette mise en œuvre d'un multiton en c objectif « élégant »? Je programme utilisation refusée »de alloc et allocWithZone: parce que la décision d'allouer ou non allouer de la mémoire doit être fait sur la base d'une clé.

Je sais pour sûr que je dois travailler avec seulement deux cas, alors j'utilise « switch-case » au lieu d'une carte.

#import "Multiton.h"

static Multiton *firstInstance = nil;
static Multiton *secondInstance = nil;

@implementation Multiton

+ (Multiton *) sharedInstanceForDirection:(enum KeyName)direction {

    return [[self allocWithKey:direction] init];
}

+ (id) allocWithKey:(enum KeyName)key {

    return [self allocWithZone:nil andKey:key];
}

+ (id) allocWithZone:(NSZone *)zone andKey:(enum KeyName)key {

    Multiton **sharedInstance;

    @synchronized(self) {

        switch (key) {
            case KEY_1:
                sharedInstance = &firstInstance;
                break;
            case KEY_2:
                sharedInstance = &secondInstance;
                break;
            default:
                [NSException raise:NSInvalidArgumentException format:@"Invalid key"];
                break;
        }
        if (*sharedInstance == nil)
            *sharedInstance = [super allocWithZone:zone];
    }

    return *sharedInstance;
}

+ (id) allocWithZone:(NSZone *)zone {

    //Do not allow use of alloc and allocWithZone
    [NSException raise:NSObjectInaccessibleException format:@"Use allocWithZone:andKey: or allocWithKey:"];
    return nil;
}

- (id) copyWithZone:(NSZone *)zone {

    return self;
}

- (id) retain {

    return self;
}

- (unsigned) retainCount {

    return NSUIntegerMax;
}

- (void) release {

    return;
}

- (id) autorelease {

    return self;
}

- (id) init {
    [super init];
    return self;
}

@end

PS: Je ne l'ai pas essayé si cela fonctionne encore, mais sa compilation proprement:)

Était-ce utile?

La solution

Je trouve singletons une mauvaise idée et cela ressemble environ quatre fois plus horrible. Le code est assez complexe, vous pouvez être sûr de passer une belle quelques heures courir après des bugs subtiles et vous vous sentirez probablement jamais à l'aise à ce sujet. Ce n'est pas bon. Vous devriez jeter cette abomination loin et câbler vos objets ensemble d'une autre manière qui ne nécessite pas beaucoup de réflexion.

Si vous aimez les modèles, vous pouvez utiliser quelque chose comme modèle d'usine au fil de vos objets. L'usine se chargera de la création de ces deux instances et les passer chaque fois que nécessaire. Et l'usine sera beaucoup plus simple que Multiton:

@interface Factory : NSObject {
    Foo *foo1, *foo2;
}
@end

@implementation Factory

- (id) init {
    [super init];
    foo1 = [[Foo alloc] init];
    foo2 = [[Foo alloc] init];
    return self;
}

Bien sûr, vous ne devez pas créer les deux cas à la fois. Vous pouvez faire tout ce que vous aimez là - cache, charge paresseux, quoi que ce soit. Le point quitte la gestion de la durée de vie Foo jusqu'à l'usine, séparé du code Foo. Ensuite, il devient beaucoup plus facile. ¶ Tous les autres objets qui ont besoin Foo sera créé et câblé par usine et recevront leur Foo par un poseur:

@implementation Factory

- (id) wireSomeClass {
    id instance = [[SomeClass alloc] init];
    [instance setFoo:foo1];
    [instance setAnotherDependency:bar];
    return [instance autorelease];
}

Ceci est d'autant plus simple alors le code de votre question.

Autres conseils

Ne pas passer outre alloc. Le problème avec dépassement alloc pour retourner une instance précédemment attribuée de la classe, comme vous le faites, est que lorsque + sharedInstance appelle [[Multiton alloc] init] ... + alloc retournera l'ancienne instance, puis -init sera re-initialiser! la meilleure pratique consiste à remplacer -init, faire la recherche de cache et d'appeler [auto release] avant de retourner l'instance mise en cache.

Si vous êtes vraiment préoccupé par le coût de cette alloc supplémentaire + (il n'y a pas beaucoup), vous faites également votre cache recherche dans + sharedInstance puis assurez-vous que tous vos clients accéder à l'instance à + sharedInstance pour éviter le alloc supplémentaire.

Le point de l'ordre: Comment vous ne savez-vous que jamais deux instances, ou besoin d'avoir deux instances? (Ou voulez avoir deux instances?) Qu'est-ce, exactement, est le point d'avoir un "Multiton"? (Et est que même un mot?)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top