You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS开发:如何更优雅实例化遵循协议的类?

优雅解决iOS中基于字符串实例化协议类的分支问题

针对你当前用大量if/else分支实例化遵循unitLoadoutDataController协议类的问题,推荐以下几种无需分支的优雅方案:

方案一:使用名称-类映射字典(最推荐)

通过创建一个显示名称与对应类的映射字典,直接根据选中的名称取出类进行实例化,维护成本极低。

实现步骤:

  1. 定义映射字典(可放在类的初始化方法、常量文件或分类中):
// 示例:在当前类的viewDidLoad或初始化方法中定义
NSDictionary<NSString *, Class> *unitClassMap = @{
    @"Heavy Intercessor Squad" : heavyIntercessorSquad.class,
    @"Eradicator Squad" : eradicatorSquad.class,
    // 依次添加剩余30个类的映射关系
};
  1. 实例化并赋值:
// 根据选中名称获取对应类
Class unitClass = unitClassMap[self.selectedUnit.name];

// 安全检查:确保类存在且遵循协议
if (unitClass && [unitClass conformsToProtocol:@protocol(unitLoadoutDataController)]) {
    self.squadToConfigure = [[unitClass alloc] init];
} else {
    // 处理异常情况,比如日志提示或默认实现
    NSLog(@"未找到对应单元类或类不遵循协议:%@", self.selectedUnit.name);
}

// 执行后续配置逻辑
if (self.squadToConfigure) {
    [self.squadToConfigure setDefaultLoadout:self.selectedUnit.name
                                      unitId:newUnitId];
}

优点:

  • 新增类仅需在字典中添加一行映射,无需修改实例化逻辑
  • 代码简洁直观,彻底消除大量if/else分支
  • 类型安全,通过协议检查避免实例化错误类

方案二:封装工厂类

如果后续实例化逻辑需要扩展(比如需要传入额外参数),可以将实例化逻辑封装到独立的工厂类中,进一步解耦业务代码。

实现示例:

  1. 创建工厂类:
@interface UnitFactory : NSObject
/// 根据单元名称创建遵循unitLoadoutDataController协议的实例
+ (id<unitLoadoutDataController>)createUnitWithName:(NSString *)unitName;
@end

@implementation UnitFactory
+ (id<unitLoadoutDataController>)createUnitWithName:(NSString *)unitName {
    NSDictionary<NSString *, Class> *classMap = @{
        @"Heavy Intercessor Squad" : heavyIntercessorSquad.class,
        @"Eradicator Squad" : eradicatorSquad.class,
        // 其他类映射
    };
    
    Class unitClass = classMap[unitName];
    if (unitClass && [unitClass conformsToProtocol:@protocol(unitLoadoutDataController)]) {
        return [[unitClass alloc] init];
    }
    return nil;
}
@end
  1. 使用工厂类实例化:
self.squadToConfigure = [UnitFactory createUnitWithName:self.selectedUnit.name];
if (self.squadToConfigure) {
    [self.squadToConfigure setDefaultLoadout:self.selectedUnit.name
                                      unitId:newUnitId];
}

优点:

  • 实例化逻辑集中管理,业务代码无需关心具体类的创建细节
  • 便于后续扩展实例化规则(比如添加缓存、参数初始化等)

方案三:运行时动态类名转换(不推荐)

如果显示名称和类名有固定的转换规则,可以通过运行时API动态获取类,但这种方式依赖名称强绑定,风险较高。

实现示例:

// 将显示名称转换为类名(示例规则:去掉空格,首单词小写,后续单词首字母大写)
- (NSString *)convertUnitNameToClassName:(NSString *)unitName {
    NSArray *words = [unitName componentsSeparatedByString:@" "];
    NSMutableString *className = [NSMutableString string];
    for (NSInteger i = 0; i < words.count; i++) {
        NSString *word = words[i];
        if (i == 0) {
            [className appendString:[word lowercaseString]];
        } else {
            [className appendString:[word capitalizedString]];
        }
    }
    return className;
}

// 动态实例化
NSString *className = [self convertUnitNameToClassName:self.selectedUnit.name];
Class unitClass = NSClassFromString(className);
if (unitClass && [unitClass conformsToProtocol:@protocol(unitLoadoutDataController)]) {
    self.squadToConfigure = [[unitClass alloc] init];
}

缺点:

  • 依赖显示名称与类名的强绑定关系,一旦名称或类名修改容易出错
  • 调试和维护成本高,无法直观看到所有映射关系

内容的提问来源于stack exchange,提问作者Doug Idle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 18:20:33