利用 AOP 模块化细节业务,确实有趣。因为我们通常情况下说起 AOP,都会想起比如“埋点”、“method swizzing”等字眼,角度比较宏观,起到了解耦的作用;本文从另一个角度出发,使用 AOP 思想对细节业务做模块分离的工作。
AOP简介 面向切面编程(也叫面向方面):Aspect Oriented Programming(AOP),是目前软件开发中的一个热点。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改 变这些行为的时候不影响业务逻辑的代码。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
在实际业务需求中,出场率很高的是UITalbeView和UICollecitonView等需要用大量代理方法配置的视图,当然这是苹果程序设计的惯例。当UI界面很复杂,业务逻辑相当多的时候,虽然把网络请求、数据处理、视图封装等都模块分离出去了,但是配置代理里面的逻辑太多,我们想要每一个类处理一部分代理方法。
首先,创建实现 UITableView 代理的三个类:
@implementation TestTableViewDigitConfig
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 80;
}
@end
@implementation TestTableViewClickConfig
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"click -- section:%ld, row:%ld", indexPath.section, indexPath.row);
}
@end
@implementation TestTableViewCellConfig
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(UITableViewCell.class)];
if (!cell) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(UITableViewCell.class)];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld行", indexPath.row];
return cell;
}
@end
如代码所见,这里将 tableView 的代理用三个类来分别实现,然后在 UIViewController 里面只需要写这些代码:
@interface TestVC ()
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) YBAOPManager *aopManager;
@property (nonatomic, strong) TestTableViewDigitConfig *digitConfig;
@property (nonatomic, strong) TestTableViewClickConfig *clickConfig;
@property (nonatomic, strong) TestTableViewCellConfig *cellConfig;
@end
@implementation TestVC
#pragma mark life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
}
#pragma mark getter
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
_tableView.tableFooterView = [UIView new];
_digitConfig = [TestTableViewDigitConfig new];
_clickConfig = [TestTableViewClickConfig new];
_cellConfig = [TestTableViewCellConfig new];
_aopManager = [YBAOPManager new];
[_aopManager addTarget:_digitConfig];
[_aopManager addTarget:_clickConfig];
[_aopManager addTarget:_cellConfig];
_tableView.delegate = _aopManager;
_tableView.dataSource = _aopManager;
}
return _tableView;
}
@end
核心代码就是将 YBAOPManager 类的使用:
当你需要使用多个对象(target)来承接一些方法的实现,初始化 YBAOPManager 实例,将这些对象实例添加到 YBAOPManager 实例中(addTarget),最后将 YBAOPManager 实例作为这些方法的第一承接者。剩下的方法分发工作就交给该类了。