Pregunta

¿Quieres que llame a esta implementación de un Multiton en Objective-C 'elegante'? Tengo programación 'no permitidas' uso de alloc y allocWithZone: debido a que la decisión de asignar o no asignar necesidades de memoria que hacerse sobre la base de una clave.

Sé con certeza que tengo que trabajar con sólo dos casos, por lo que estoy usando 'switch de los casos' en lugar de un 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

PD: no he probado si esto funciona hasta ahora, pero su compilación limpia:)

¿Fue útil?

Solución

Me parece una mala idea únicos y esto se ve cerca de cuatro veces horrible. El código es bastante compleja, puede estar seguro de pasar una agradable pocas horas persiguiendo a errores sutiles en ella y es probable que nunca se sienten cómodos al respecto. Eso no es bueno. Usted debe lanzar esta abominación de distancia y conectar los objetos juntos en alguna otra forma que no requiere mucho pensamiento.

Si te gusta patrones, se puede usar algo similar al patrón de fábrica para conectar sus objetos. La fábrica se hará cargo de la creación de esos dos casos y pasarlos siempre que sea necesario. Y la fábrica va a ser mucho más 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;
}

Por supuesto que no tiene que crear ambos casos a la vez. Puedes hacer lo que quieras allí - caché, la carga perezosa, cualquier cosa. El punto abandona el manejo de Foo curso de la vida hasta la fábrica, separado del código Foo. Luego se pone mucho más fácil. ¶ Todos los demás objetos que necesitan Foo se creará y por cable a través de la fábrica y se entregarán los Foo través de un regulador:

@implementation Factory

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

Esto es todo mucho más sencillo entonces el código de su pregunta.

Otros consejos

No anule alloc. El problema con anulando alloc para devolver una instancia previamente asignado de la clase, como lo hace, es que cuando + sharedInstance llama [[Multiton alloc] init] ... + alloc devolverá la instancia antigua, a continuación, -init se reinicializarlo! lo más recomendable es reemplazar -init, haciendo la búsqueda en la caché y llamando [comunicado de auto] antes de regresar a la instancia en caché.

Si usted es realmente preocupados por el costo de ese extra + alloc (que no es mucho), también hace su búsqueda en la caché de + sharedInstance y luego asegurarse de que todos sus clientes acceder a la instancia a través + sharedInstance para evitar la alloc adicional.

Cuestión de orden: ¿Cómo sabe que usted sólo tenga dos casos, o la necesidad de tener dos casos? (O quiere tener dos instancias?) ¿Qué, exactamente, es la punto de tener un "Multiton"? (Y es que incluso una palabra?)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top