带参数的单例模式

Jan*_*Jan 9 design-patterns objective-c

在我的iPhone应用程序中,我使用AFHTTPClient的子类来访问其余的Web服务.我希望我的所有请求都由我的API客户端的一个实例处理,因此我使用单例模式.

当服务仅在一次URL上运行时,这可以正常工作.我可以使用常量值来设置URL.

现在,在应用程序的最终版本中,每个应用程序实际上将与将安装在公司网络中的另一个服务进行通信.

所以我将从远程配置中获取服务URL.单身人士模式在这里仍然是一个不错的选择吗?如果URL在应用程序的运行时间实际上甚至可以更改,我应该如何参数化?

干杯

#import "FooAPIClient.h"
#import "AFJSONRequestOperation.h"

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1";

@implementation FooAPIClient

+ (instancetype)sharedClient {
    static FooAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]];
    });

    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }

    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"application/json"];

    return self;
}

@end
Run Code Online (Sandbox Code Playgroud)

Jan*_*Jan 1

这可能是解决方案。无需子类化 AFHTTPClient,只需将其设置为属性并在 URL 更改时重新实例化它:

#import "FooAPIClient.h"
#import "AFJSONRequestOperation.h"
#import "AFHTTPClient.h"

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1";

@interface FooAPIClient ()
@property AFHTTPClient * httpClient;
@end

@implementation FooAPIClient

+ (instancetype)sharedClient {
    static FooAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]];
    });

    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {

    self = [super init];
    if (!self) {
        self.httpClient = [self setupClientForURL:url];
    }
    return self;
}

-(AFHTTPClient*) setupClientForURL:(NSURL*) url {
    AFHTTPClient * httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
    [httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [httpClient setDefaultHeader:@"Accept" value:@"application/json"];
    return httpClient;
}

#pragma mark - RemoteConfigurationDelegate

-(void) apiURLChanged:(NSURL*) newURL {
    self.httpClient = [self setupClientForURL:newURL];
}


#pragma mark - Public

-(void) consumeAPI:(CompletionBlock) completion {
    [self.httpClient getPath:@"foo" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        if(completion) {
            completion(responseObject, nil);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if(completion) {
            completion(nil, error);
        }
    }];
}



@end
Run Code Online (Sandbox Code Playgroud)