2010-03-24 5 views
3

이 멀티 톤 구현을 objective-c 'elegant'이라고할까요? 프로그래밍 방식으로 '허용되지 않음'인 allocallocWithZone:을 사용했는지 여부는 키를 기준으로 메모리를 할당하거나 할당하지 않을 것인지 결정해야하기 때문입니다.Objective C에서 우아하고 정확한 '멀티 톤 구현?

저는 두 인스턴스 만 사용해야하므로지도 대신 'switch-case'를 사용하고 있습니다.

#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 : 당신은 어떻게 당신이 오직 두 개의 인스턴스를해야합니다 알고, 또는 않습니다이 아직 작동하지만 깔끔하게 컴파일 : 순서

+1

"key"는 char 대신 enum이어야합니다. –

+0

@David : 고정되어 있습니다! – ArjunShankar

답변

3

싱글 톤은 나쁜 생각이며 이것은 약 4 배나 끔찍한 것으로 보입니다. 코드가 복잡하기 때문에 미묘한 버그를 쫓는 멋진 몇 시간을 보낼 수 있으며 아마 그것에 대해 결코 편하지 않을 것입니다. 그건 좋지 않아. 이 가증 한 일을 버려야하고, 생각을별로 필요로하지 않는 다른 방법으로 물건을 연결해야합니다.

패턴이 마음에 들면 공장 패턴과 비슷한 것을 사용하여 객체를 연결할 수 있습니다. Factory는이 두 인스턴스를 생성하고 필요할 때마다 전달합니다. 그리고 공장은 멀티 톤보다 훨씬 간단합니다 :

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

@implementation Factory 

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

물론 두 인스턴스를 동시에 만들 필요는 없습니다. 캐시, 게으른로드 등 무엇이든 원하는대로 할 수 있습니다. 요점은 Foo 코드와 별도로 공장까지 Foo 평생 관리를 맡기는 것입니다. 그런 다음 훨씬 쉽게됩니다. ¶ Foo 작성 및 유선 공장을 통해받을 것이다 필요한 모든 다른 객체들은 세터를 통해 Foo :

@implementation Factory 

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

이 다음 질문의 코드 모든 훨씬 더 간단합니다.

+0

그 복합체와 그의 코드 워드 어리 어인이 지적한 바에 따르면, 그 대답은 점점 더 악화 될 것입니다. 그리고 이것을 읽은 후에 : [http://stackoverflow.com/questions/2410830/apple-singleton-example-query/2411685#2411685], 나는 더 간단한 것을 할 필요가 있다고 결정했습니다. 이런 식으로 멀티 톤을 강요하면 더 이상 우아 해 보이지 않습니다. – ArjunShankar

0

점을 경우 나는 밖으로 시도하지했습니다 두 개의 인스턴스가 있어야합니까? (또는 두 개의 인스턴스를 갖고 싶습니까?) "멀티 톤"을 가지고있는 포인트은 정확히 무엇입니까? (그리고 그것은 심지어 단어입니까?)

+0

멀티 톤은 싱글 톤 개념을 확장 한 디자인 패턴입니다. http://en.wikipedia.org/wiki/Multiton_pattern – ArjunShankar

+0

다음은 왜 두 인스턴스가 필요한지 예제입니다 (오히려 _my_를 두 개 필요로하는 이유) : 두 개의 스레드에서 sqlite3 데이터베이스에 액세스하려고합니다. 이제 sqlite3은 스레드간에 연결을 공유하지 않으면 스레드로부터 안전합니다. => 각 스레드마다 고유 한 연결이 있는지 확인해야합니다.sqlite3 연결이 멀티 톤의 인스턴스에 해당하고 각 스레드가 자신을 식별 할 수 있다면 스레드 당 정확히 하나의 인스턴스가 있는지 확인하는 좋은 방법입니다. – ArjunShankar

+2

이것은 단지 프로그래밍 연습이 아닌 한, 다른 사람들이 sqlite 스레딩을 어떻게 수행했는지 예제를 찾을 수 있습니다. 아마도 multitons와 같이 지나치게 복잡한 구문 대신 간단한 뮤텍스를 사용했을 것입니다. –

2

alloc을 무시하지 마십시오. 이전에 할당 한 클래스 인스턴스를 반환하도록 alloc을 재정의하는 문제는 + sharedInstance가 [[Multiton alloc] init ...]을 호출 할 때 + alloc이 이전 인스턴스를 반환 할 경우 -init가 다시 호출됩니다. 그것을 초기화하십시오! 가장 좋은 방법은 캐시 조회를 수행하고 캐시 된 인스턴스를 반환하기 전에 [self release]를 호출하여 -init를 무시하는 것입니다.

의 경우 + 추가 비용 (약은 아닙니다)에 염려하지만 실제로 + sharedInstance에서 캐시 조회를 수행 한 다음 모든 클라이언트가 + sharedInstance를 통해 인스턴스에 액세스하는지 확인하십시오. 여분의 할당을 피하십시오.

+0

당신 말이 맞아요. 나는 할당 된 인스턴스를 다시 초기화하지 않고 (그리고 코드의 또 다른 비트를 추가하지 않도록) init을 똑똑하게 만드는 것으로 생각하고있다. 기본적으로 멀티 톤을 강요한다는 전체 생각이 나쁘다는 느낌을 받는다. – ArjunShankar