如何使我的单例类可扩展?

时间:2013-04-19 10:49:14

标签: ios objective-c singleton

我们的静态库中有一个单例类。这是一个单身人士,因为我们希望能够记住"它的状态始终如此。从本质上讲,它是一个用户管理单例。

它有一个属性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吗?或者我是否必须重写这些单例方法来处理" new"儿童班?

有没有办法可以修改这些方法,以便第三方可以轻松扩展这个类?

由于

2 个答案:

答案 0 :(得分:1)

更好的单身人士模式:

// 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

如果您是子类,则单个实例将设置为首先调用的任何内容,例如:

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

仅这一点就可以了:

[[Cow sharedInstance]moo];

答案 1 :(得分:0)

Beter设计将使用Composition然后继承。声明协议AuthenticationDelegate

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

在UserManager中有一个属性,默认情况下指向UserManager。

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

@property (assign) id<AuthenticationDelegate>  authenticator

+ (id)sharedInstance;

如果客户希望通过他们的方法进行身份验证,那么他们必须向AuthenticationDelegate协议确认并实现其方法。他们必须将authenticator属性设置为其所限定的类。然而它的单身人士。因此,只要对象被实例化,他们就可以设置它。因此他们可以使用他们的身份验证器

但要确保验证者剂量指向零。您可以实现setAuthenticator:方法,以便当客户端将此设置为nil时,authenticator将指向UserManager。

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.
}

希望这会有所帮助......