2013-04-19 3 views
3

우리는 정적 라이브러리 중 하나에 싱글 톤 클래스를 가지고 있습니다. 우리가 항상 그 상태를 "기억할"수 있기를 원하기 때문에 이것은 하나의 싱글 톤입니다. 본질적으로 그것은 사용자 관리 싱글 톤입니다.내 싱글 톤 클래스를 확장 가능하게 만드는 방법?

속성은 User *user이고, 방법은 - (void)authenticateUser입니다.

- (void)authenticateUser 메서드를 만들려는 클라이언트에게 전달하려고합니다. 이렇게하려면 UserManager 클래스를 확장하여 메서드를 재정의한다고 생각했습니다.

그러나 싱글 톤이므로 - (id)sharedInstance 및 맞춤 alloc 메서드가 있습니다. 그들 모두는 다음과 같다 :

그래서이 주어
static UserManager *_sharedInstance = nil; 

+ (id)sharedInstance { 
    @synchronized([UserManager class]) { 
     if(!_sharedInstance){ 
      id temp = [[self alloc] init]; 
      [temp class]; 
     } 
     return _sharedInstance; 
    } 
    return nil; 
} 

+ (id)alloc { 
    @synchronized([UserManager class]) { 
     NSAssert(_sharedInstance == nil, @"Attempted to allocate a second instance of a singleton"); 
     _sharedInstance = [super alloc]; 
     return _sharedInstance; 
    } 
    return nil; 
} 

, 그것은 서브 클래스 화해,이 UserManager 클래스를 확장 할 수 있습니다? 함수를 재정의하는 ChildUserManager을 만들 수 있습니까? 아니면 "새"하위 클래스를 처리하기 위해 이러한 싱글 톤 메서드를 다시 작성해야합니까?

타사에서 쉽게이 클래스를 확장 할 수 있도록 이러한 방법을 수정할 수있는 방법이 있습니까?

감사

+0

, 당신은 그것을 설정하는 사람을 위험이 있습니다. – Jano

+0

아마도 static이 구현 안에 있기 때문에이 클래스 밖에서는 사용할 수 없습니까? –

+0

죄송합니다. 컴파일 단위에서만 볼 수 있습니다. – Jano

답변

0

베터 디자인은 Composition then Inheritance를 사용합니다. 프로토콜을 선언하십시오. AuthenticationDelegate

@protocol AuthenticationDelegate 
@optional 
-(void) authenticateUser:(User*)inUser; 
@end 

기본적으로 UserManager를 가리키는 UserManager 속성이 있습니다.

@class UserManager : NSObject <AuthenticationDelegate> { 
    ...... 
} 

@property (assign) id<AuthenticationDelegate> authenticator 

+ (id)sharedInstance; 

클라이언트가 자신의 방법으로 인증하려는 경우 인증 시도 프로토콜로 확인하고 해당 방법을 구현해야합니다. 그들은 authenticator 프로퍼티를 제한 할 클래스에 설정해야합니다. 그러나 그것의 싱글 톤. 따라서 객체를 인스턴스화하는 즉시 설정할 수 있습니다. 따라서 인증자를 사용할 수 있습니다.

하지만 인증 담당자가 nil을 가리키는 지 확인하십시오. 클라이언트가이 값을 nil로 설정할 때 authenticator가 UserManager를 가리킬 수 있도록 setAuthenticator : 메소드를 구현할 수 있습니다. 정적 내부 ALLOC가 아닌 경우이 도움이

static UserManager *_sharedInstance = nil; 

@implementation UserManager 

@synthasize authenticator; 

+ (id)sharedInstance { 
    @synchronized([UserManager class]) { 
     if(!_sharedInstance){ 
      id temp = [[self alloc] init]; 
      [temp class]; 
     } 
     return _sharedInstance; 
    } 
    return nil; 
} 

+ (id)alloc { 
    @synchronized([UserManager class]) { 
     NSAssert(_sharedInstance == nil, @"Attempted to allocate a second instance of a  singleton"); 
     _sharedInstance = [super alloc]; 
     return _sharedInstance; 
    } 
    return nil; 
} 

-(void)init { 
    self = [super init]; 
    if (self) { 
     self.authenticator = nil; 
    } 
} 

-(void)setAuthenticator:(id<AuthenticationDelegate>)inAuthenticator { 
    if (!inAuthenticator) { 
     __authenticator = self; 
    } else { 
     __authenticator = inAuthenticator; 
    } 
} 

#pragma mark - AuthenticationDelegate 

-(void) authenticateUser:(User*)inUser 
{ 
    // Your Authentication Code. 
} 

희망 ...

+0

이것은 매우 흥미로운 대답입니다. 한 가지 단점은 대부분의 클래스와 메서드가 확장 가능/재정의 가능해야한다는 것입니다.이 메서드를 모든 메서드에 구현하는 것은 다소 번거로운 작업 일 수 있습니다. 그러나 그것의 재미있는 아이디어와 제가 좀 더 탐구 할 방법은 그것이 할 수있는 방법이 있는지보십시오. –

+0

iOS 환경을 쉽게 관리 할 수 ​​있다면 @synchronized를 사용하는 이유는 무엇입니까? 한 번에 하나의 액세스를 제어 할 수 있습니까? 아니면 일반화하기를 원하십니까? – seufagner

1

더 나은 싱글 톤 패턴 :

[Animal sharedInstance]; // instance set to Animal 
[[Cow sharedInstance] moo]; // unknown selector 'moo' because the instance is Animal 

이 혼자 일 것입니다 : 당신이 서브 클래스 경우

// UserManager.h 

#import <Foundation/Foundation.h> 

@interface UserManager : NSObject 

+(instancetype)sharedInstance; 

// clue for improper use (produces compile time error) 
+(instancetype) alloc __attribute__((unavailable("alloc not available, call sharedInstance instead"))); 
-(instancetype) init __attribute__((unavailable("init not available, call sharedInstance instead"))); 
+(instancetype) new __attribute__((unavailable("new not available, call sharedInstance instead"))); 

@end 


// UserManager.m 

#import "UserManager.h" 

@implementation UserManager 

+(instancetype) sharedInstance { 
    static dispatch_once_t pred; 
    static id shared = nil; 
    dispatch_once(&pred, ^{ 
     shared = [[super alloc] initUniqueInstance]; 
    }); 
    return shared; 
} 

-(instancetype) initUniqueInstance { 
    return [super init]; 
} 

@end 

, 단일 인스턴스는 예를 들어, 첫 번째라고 무엇으로 설정됩니다 tho :

[[Cow sharedInstance]moo]; 
+0

내 질문에서 내가 요구하는 것은 싱글 톤으로 가능하지 않다는 말입니까? 그러므로 표준 객체로 만들어야합니까? 아니면 싱글 톤 사용에 대한 조언을 해 주시겠습니까? –

+0

Objective-C에서 클라이언트가 런타임 기능을 사용하여 싱글 톤 인스턴스를 n 개 생성하지 못하게 할 수 없습니다. dispatch_once를 사용하는 싱글 톤에 대한 더 나은 관용구가 있습니다. 싱글 톤을 확장하는 것은 조금 이상합니다. 인정해야합니다. Objective-C는 동적이기 때문에 추상 클래스를 사용하는 데 별다른 의미가 없으므로 init 메소드를 비활성화 할 수있는 경우에도 클래스를 문서화하고 클라이언트의 상식을 나머지 부분에 적용하면 IMO가 더 좋습니다. – Jano

+0

흠 ... 좋아. 확실히 생각을위한 음식. 나는 그것을 들여다보고 모든 것을 되돌리기 위해 얼마나 많은 일이 있을지를 볼 수 있습니다! :) thanks –

관련 문제