控制反转(IoC)容器的设计

定义

用iOS开发环境来举例,IoC容器的核心功能负责对象创建、依赖查找和依赖注入,这些功能都需要借助运行时runtime的反射实现

使用protocol

在IoC容器中,就算通过反射可以创建Class 和instance,但是实际开发过程中还是有缺陷,因为还是不能很好地访问Class的属性与方法,这时候可以通过iOS的Protocol来访问。

例子
在IoC容器中,创建一个Class的Protocol,此Protocol声明了Class的所有方法和属性,然后在Class中实现此Protocol接口便可。

//
//  ClassAProtocol.h
//  IOCAdapter
//

#ifndef ClassAProtocol_h
#define ClassAProtocol_h

NS_ASSUME_NONNULL_BEGIN

@protocol ClassAProtocol 

@property (nonatomic, copy) NSString *var;

- (void)testMethod;

+ (void)testClassMethod;
@end

NS_ASSUME_NONNULL_END


#endif /* ClassAProtocol_h */
#import 
#import 

NS_ASSUME_NONNULL_BEGIN

@interface ClassA : NSObject 

@property (nonatomic, copy) NSString *var;

- (void)testMethod;

+ (void)testClassMethod;


@end

NS_ASSUME_NONNULL_END

IoC容器 Class缓存

因为从IoC容器中获取Class的次数较为频繁,我们可以在容器中加入缓存功能。


@interface IOCCacheServiceDict:NSObject

+ (instancetype)sharedInstance;

- (Class) getClass:(NSString*) key;

- (void) addService:(NSString*) key implClass:(Class) implClass;

@end


@implementation IOCCacheServiceDict{
    NSMutableDictionary *_dictServices;
    NSRecursiveLock *_lock;
}

+ (instancetype)sharedInstance{
    static dispatch_once_t onceToken;
    static IOCCacheServiceDict* dict;
    dispatch_once(&onceToken, ^{
        dict = [[self alloc] init];
    });
    return dict;
}

- (instancetype)init{
    self = [super init];
    if (!self) {
        return nil;
    }
    _dictServices = [NSMutableDictionary dictionaryWithCapacity:25];
    _lock = [[NSRecursiveLock alloc] init];
    return self;
}


- (Class) getClass:(NSString*) key{
    [_lock lock];
    Class cls = _dictServices[key];
    [_lock unlock];
    return cls;
}

- (void) addService:(NSString*) key implClass:(Class) implClass{
    [_lock lock];
    [_dictServices setValue:implClass forKey:key];
    [_lock unlock];
}

@end

获取Class


Class IOCGetServiceClass(Protocol* protocol){
    NSString* protocolName = NSStringFromProtocol(protocol);
    Class cls = [[IOCCacheServiceDict sharedInstance] getClass:protocolName];
    if (nil != cls){
        return cls;
    }
    NSString *protocolSubffix = @"Protocol";
    return IOCGetServiceClassWithProtocol(protocol, protocolName, protocolSubffix);

}

Class IOCGetServiceClassWithProtocol(Protocol* protocol, NSString* protocolName, NSString* protocolSubffix){
    NSString *className = [protocolName hasSuffix:protocolSubffix] ? [protocolName substringToIndex:protocolName.length - protocolSubffix.length] : protocolName;
    Class cls = NSClassFromString(className);
    IOCRegisterServiceForStringProtocol(protocolName, cls);

    return cls;
}

BOOL IOCRegisterServiceForStringProtocol(NSString* protocol, Class implClass){
    if (nil == protocol || nil == implClass){
        return NO;
    }
    if ([[IOCCacheServiceDict sharedInstance] getClass:protocol]) {
        return NO;
    }else{
        [[IOCCacheServiceDict sharedInstance] addService:protocol implClass:implClass];
        return YES;
    }
}

获取 instance


id IOCGetServiceInstance(Protocol* protocol){
    Class cls = IOCGetServiceClass(protocol);
    id value = [cls new];
    return value;
}

调用

在不同的模块中,可以通过以下方法,来访问其他模块的Class和Class的属性、方法。

[IOCGetServiceClass(@protocol(ClassAProtocol)) testClassMethod];

[IOCGetServiceInstance(@protocol(ClassAProtocol)) testMethod];

[IOCGetServiceInstance(@protocol(ClassAProtocol)) var];

你可能感兴趣的:(控制反转(IoC)容器的设计)