Pergunta

Você chamaria essa implementação de um multiton no objetivo-c de 'elegante'?Eu 'proibido' programaticamente o uso de alloc e allocWithZone: porque a decisão de alocar ou não memória precisa ser feita com base em uma chave.

Tenho certeza de que preciso trabalhar com apenas duas instâncias, então estou usando 'switch-case' em vez de um mapa.

#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:Ainda não testei se isso funciona, mas está compilando de forma limpa :)

Foi útil?

Solução

Acho os solteiros uma má ideia e isso parece quatro vezes mais horrível.O código é bastante complexo, você pode ter certeza de que gastará algumas horas perseguindo bugs sutis nele e provavelmente nunca se sentirá confortável com isso.Isso não é bom.Você deveria jogar fora essa abominação e conectar seus objetos de alguma outra maneira que não exija tanta reflexão.

Se você gosta de padrões, você pode usar algo parecido com o padrão Factory para conectar seus objetos.A Fábrica se encarregará de criar essas duas instâncias e passá-las sempre que necessário.E o Factory será muito mais simples que o Multiton:

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

@implementation Factory

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

Claro que você não precisa criar as duas instâncias ao mesmo tempo.Você pode fazer o que quiser lá – cache, carregamento lento, qualquer coisa.A questão é deixar o Foo gerenciamento vitalício até a Fábrica, separado do Foo código.Então fica muito mais fácil.¶ Todos os outros objetos que necessitam Foo serão criados e conectados pela Fábrica e receberão seus Foo através de um setter:

@implementation Factory

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

Tudo isso é muito mais simples que o código da sua pergunta.

Outras dicas

Não substitua o aloc. O problema de substituir o Alloc para retornar uma instância alocada anteriormente da classe, como você faz, é que, quando +SharedInstance chama [[Multiton alloC] init] ... +aloc retornará a instância antiga, então -Init irá reinicializar-o! A prática recomendada é substituir -init, fazendo a pesquisa de cache e chamando [auto -lançamento] antes de retornar a instância em cache.

Se vocês são verdade Preocupado com o custo desse Alloc extra +(não é muito), você também faz sua pesquisa de cache no +compartilhamento e, em seguida, garante que todos os seus clientes acessem a instância através do +SharedInstance para evitar o Allow Extra.

Ponto de ordem: Como você sabe que você só terá duas instâncias ou precisará ter duas instâncias? (Ou quer ter duas instâncias?) Qual é exatamente o ponto de ter um "multiton"? (E isso é mesmo uma palavra?)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top