4

我们的一个静态库中有一个单例类。它是一个单例,因为我们希望能够始终“记住”它的状态。本质上它是一个用户管理单例。

它有一个属性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覆盖函数的函数吗?还是我必须重写这些单例方法来处理“新”子类?

有什么方法可以修改这些方法以使第 3 方可以轻松扩展此类?

谢谢

4

2 回答 2

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];
于 2013-04-19T11:13:48.500 回答
0

更好的设计是使用组合然后继承。声明一个协议 AuthenticationDelegate

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

在 UserManager 中有一个默认指向 UserManager 的属性。

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

@property (assign) id<AuthenticationDelegate>  authenticator

+ (id)sharedInstance;

您的客户如果想通过他们的方法进行身份验证,那么他们必须向 AuthenticationDelegate 协议确认自己并实现其方法。他们必须将身份验证器属性设置为限制为 . 然而它的单例。所以他们可以在他们的对象被实例化后立即设置它。因此他们可以使用他们的 Authenticator。

但是要确保验证器指向 nil。您可以实现 setAuthenticator: 方法,以便在客户端将其设置为 nil 时,验证器将指向 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.
}

希望这可以帮助...

于 2013-04-19T13:22:31.223 回答