MST

星途 面试题库

面试题:Objective-C中工厂模式与抽象工厂模式的性能与优化

在大规模使用Objective-C工厂模式和抽象工厂模式的应用中,可能会遇到哪些性能问题?比如内存管理、对象创建开销等方面。针对这些性能问题,你有哪些优化策略?请结合实际的Objective-C代码示例进行说明。
19.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

可能遇到的性能问题

  1. 内存管理
    • 对象创建与释放开销:工厂模式下频繁创建和释放对象,会增加内存分配和释放的开销。例如在一个游戏开发场景中,使用工厂模式创建大量游戏道具对象(如子弹、武器等),若每次创建都进行内存分配,会导致内存碎片问题,降低内存分配效率。
    • 循环引用:在复杂的对象关系中,可能由于工厂创建的对象之间存在相互引用,导致循环引用,从而使对象无法正常释放,造成内存泄漏。比如一个视图控制器通过工厂创建一个自定义视图,而该视图又持有对视图控制器的引用,就可能引发循环引用。
  2. 对象创建开销
    • 初始化开销:抽象工厂模式可能涉及创建复杂对象,这些对象初始化过程可能包含大量计算、数据加载等操作,导致创建时间过长。例如创建一个多媒体处理对象,初始化时需要加载大量的音频、视频编解码库,这会耗费较多时间。
    • 反射开销(在Objective - C中类似情况):虽然Objective - C没有严格意义上的反射,但在工厂模式中通过字符串来动态创建类实例时,会涉及到运行时查找类等操作,带来一定开销。比如通过NSClassFromString根据类名创建对象,相比直接创建对象会有额外开销。

优化策略及代码示例

  1. 内存管理优化
    • 对象池
      • 原理:提前创建一定数量的对象并放入对象池中,需要时从池中获取,使用完后放回池中,减少内存分配和释放次数。
      • 示例
@interface ObjectPool : NSObject

@property (nonatomic, strong) NSMutableArray *pool;
@property (nonatomic, assign) NSInteger maxCount;

+ (instancetype)sharedPool;
- (id)getObject;
- (void)returnObject:(id)object;

@end

@implementation ObjectPool

+ (instancetype)sharedPool {
    static ObjectPool *pool = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        pool = [[ObjectPool alloc] init];
        pool.pool = [NSMutableArray array];
        pool.maxCount = 10;
        for (int i = 0; i < pool.maxCount; i++) {
            id obj = [[NSObject alloc] init];
            [pool.pool addObject:obj];
        }
    });
    return pool;
}

- (id)getObject {
    if (self.pool.count > 0) {
        id obj = self.pool.lastObject;
        [self.pool removeLastObject];
        return obj;
    } else {
        return [[NSObject alloc] init];
    }
}

- (void)returnObject:(id)object {
    if (self.pool.count < self.maxCount) {
        [self.pool addObject:object];
    }
}

@end

在工厂类中使用对象池:

@interface MyObjectFactory : NSObject

+ (id)createObject;

@end

@implementation MyObjectFactory

+ (id)createObject {
    return [[ObjectPool sharedPool] getObject];
}

@end
- **避免循环引用**:
    - **原理**:使用弱引用(`weak`)或无主引用(`unowned`在ARC下类似功能)来打破循环引用。
    - **示例**:
@interface CustomView : UIView

@property (nonatomic, weak) id delegate;

@end

@implementation CustomView

@end

@interface ViewController : UIViewController

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    CustomView *customView = [[CustomView alloc] initWithFrame:self.view.bounds];
    customView.delegate = self;
    [self.view addSubview:customView];
}

@end
  1. 对象创建开销优化
    • 延迟初始化
      • 原理:将对象初始化中一些耗时操作延迟到真正需要使用该对象时执行。
      • 示例
@interface ExpensiveObject : NSObject

@property (nonatomic, strong) NSData *largeData;

- (void)loadLargeData;

@end

@implementation ExpensiveObject

- (void)loadLargeData {
    // 模拟加载大量数据
    self.largeData = [NSData dataWithContentsOfFile:@"largeFile.dat"];
}

@end

@interface ExpensiveObjectFactory : NSObject

+ (ExpensiveObject *)createObject;

@end

@implementation ExpensiveObjectFactory

+ (ExpensiveObject *)createObject {
    ExpensiveObject *obj = [[ExpensiveObject alloc] init];
    // 这里不立即加载数据
    return obj;
}

@end

在使用时:

ExpensiveObject *expensiveObj = [ExpensiveObjectFactory createObject];
// 当真正需要使用largeData时再加载
[expensiveObj loadLargeData];
- **减少动态查找**:
    - **原理**:尽量避免通过字符串动态查找类创建对象,改为静态创建。
    - **示例**:
    - 原始动态创建:
NSString *className = @"MyClass";
Class class = NSClassFromString(className);
id obj = [[class alloc] init];
    - 静态创建优化:
MyClass *obj = [[MyClass alloc] init];