面试题答案
一键面试1. iOS开发框架中可能用到适配器模式的地方及举例
- UIKit 与自定义视图交互:比如当我们需要在项目中使用第三方图表库,但图表库的视图接口与我们现有 UIKit 视图使用方式不兼容时。例如第三方图表库要求以特定的类继承关系和方法调用设置数据,而我们的项目遵循 UIKit 的常规视图添加和数据设置方式。
- 网络层数据适配:当从不同的 API 获取数据,数据格式不同,但我们希望在项目中以统一的方式处理这些数据。如一个 API 返回 JSON 格式数据是扁平结构,另一个 API 返回 JSON 是嵌套结构,而我们的业务逻辑期望以相同的对象模型处理数据。
2. 具体实现思路分析
以 UIKit 与第三方图表库为例:
- 定义目标接口:这是我们项目中期望的与视图交互的接口,比如在 UIKit 中,视图可能通过
addSubview:
方法添加到父视图,数据设置可能通过自定义属性。 - 适配者:即第三方图表库的视图类,它有自己特定的接口来添加到父视图(可能是特定的
attach
方法)和设置数据(如setChartData:
方法,且数据格式特定)。 - 适配器:创建一个适配器类,它继承自适配者(如果是类适配器模式)或者包含适配者对象(对象适配器模式),同时实现目标接口。在实现目标接口方法时,将目标接口方法的调用转换为适配者相应方法的调用。例如在
addSubview:
方法实现中,调用适配者的attach
方法;在设置数据的目标接口方法中,将我们项目的数据格式转换为适配者需要的数据格式,再调用setChartData:
方法。
3. 项目中模仿应用场景的类结构和方法调用逻辑设计
-
类结构:
- 目标视图类(TargetView):定义标准的视图操作接口,如
addSubview:
、removeFromSuperview
、updateData:
等方法。 - 第三方图表库视图类(ThirdPartyChartView):即适配者,有自己的视图添加和数据设置接口,如
attach
、detach
、setChartData:
等。 - 适配器类(ChartViewAdapter):继承自
ThirdPartyChartView
(类适配器模式)或者包含ThirdPartyChartView
对象(对象适配器模式),同时实现TargetView
接口。
- 目标视图类(TargetView):定义标准的视图操作接口,如
-
方法调用逻辑:
- 在视图添加时,我们的业务代码会调用
TargetView
的addSubview:
方法,实际这个方法在ChartViewAdapter
中实现,ChartViewAdapter
内部调用ThirdPartyChartView
的attach
方法。 - 当更新数据时,业务代码调用
TargetView
的updateData:
方法,ChartViewAdapter
会将传入的数据进行格式转换,然后调用ThirdPartyChartView
的setChartData:
方法。例如:
- 在视图添加时,我们的业务代码会调用
// 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:@[]];