MST

星途 面试题库

面试题:Objective-C 适配器模式在iOS框架中的应用分析

在iOS开发框架中,哪些地方可能会用到适配器模式?请举例说明,并分析其具体实现思路,以及如果让你在自己的项目中模仿类似的应用场景使用适配器模式,你会如何设计类结构和方法调用逻辑。
17.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. iOS开发框架中可能用到适配器模式的地方及举例

  • UIKit 与自定义视图交互:比如当我们需要在项目中使用第三方图表库,但图表库的视图接口与我们现有 UIKit 视图使用方式不兼容时。例如第三方图表库要求以特定的类继承关系和方法调用设置数据,而我们的项目遵循 UIKit 的常规视图添加和数据设置方式。
  • 网络层数据适配:当从不同的 API 获取数据,数据格式不同,但我们希望在项目中以统一的方式处理这些数据。如一个 API 返回 JSON 格式数据是扁平结构,另一个 API 返回 JSON 是嵌套结构,而我们的业务逻辑期望以相同的对象模型处理数据。

2. 具体实现思路分析

以 UIKit 与第三方图表库为例:

  • 定义目标接口:这是我们项目中期望的与视图交互的接口,比如在 UIKit 中,视图可能通过 addSubview: 方法添加到父视图,数据设置可能通过自定义属性。
  • 适配者:即第三方图表库的视图类,它有自己特定的接口来添加到父视图(可能是特定的 attach 方法)和设置数据(如 setChartData: 方法,且数据格式特定)。
  • 适配器:创建一个适配器类,它继承自适配者(如果是类适配器模式)或者包含适配者对象(对象适配器模式),同时实现目标接口。在实现目标接口方法时,将目标接口方法的调用转换为适配者相应方法的调用。例如在 addSubview: 方法实现中,调用适配者的 attach 方法;在设置数据的目标接口方法中,将我们项目的数据格式转换为适配者需要的数据格式,再调用 setChartData: 方法。

3. 项目中模仿应用场景的类结构和方法调用逻辑设计

  • 类结构

    • 目标视图类(TargetView):定义标准的视图操作接口,如 addSubview:removeFromSuperviewupdateData: 等方法。
    • 第三方图表库视图类(ThirdPartyChartView):即适配者,有自己的视图添加和数据设置接口,如 attachdetachsetChartData: 等。
    • 适配器类(ChartViewAdapter):继承自 ThirdPartyChartView(类适配器模式)或者包含 ThirdPartyChartView 对象(对象适配器模式),同时实现 TargetView 接口。
  • 方法调用逻辑

    • 在视图添加时,我们的业务代码会调用 TargetViewaddSubview: 方法,实际这个方法在 ChartViewAdapter 中实现,ChartViewAdapter 内部调用 ThirdPartyChartViewattach 方法。
    • 当更新数据时,业务代码调用 TargetViewupdateData: 方法,ChartViewAdapter 会将传入的数据进行格式转换,然后调用 ThirdPartyChartViewsetChartData: 方法。例如:
// TargetView 接口
@protocol TargetView <NSObject>
- (void)addSubview:(UIView *)view;
- (void)removeFromSuperview;
- (void)updateData:(NSArray *)data;
@end

// 第三方图表库视图类
@interface ThirdPartyChartView : UIView
- (void)attach;
- (void)detach;
- (void)setChartData:(NSDictionary *)chartData;
@end

// 适配器类
@interface ChartViewAdapter : ThirdPartyChartView <TargetView>
@property (nonatomic, strong) ThirdPartyChartView *thirdPartyChart; // 对象适配器模式使用

- (instancetype)initWithThirdPartyChart:(ThirdPartyChartView *)chart;
@end

@implementation ChartViewAdapter
- (instancetype)initWithThirdPartyChart:(ThirdPartyChartView *)chart {
    self = [super init];
    if (self) {
        self.thirdPartyChart = chart;
    }
    return self;
}

- (void)addSubview:(UIView *)view {
    [self.thirdPartyChart attach];
}

- (void)removeFromSuperview {
    [self.thirdPartyChart detach];
}

- (void)updateData:(NSArray *)data {
    NSMutableDictionary *chartData = [NSMutableDictionary dictionary];
    // 数据格式转换逻辑
    [self.thirdPartyChart setChartData:chartData];
}
@end

在业务代码中:

ThirdPartyChartView *thirdPartyChart = [[ThirdPartyChartView alloc] init];
ChartViewAdapter *adapter = [[ChartViewAdapter alloc] initWithThirdPartyChart:thirdPartyChart];
// 以 TargetView 接口方式调用
[adapter addSubview:nil];
[adapter updateData:@[]];