架构设计之MVP模式

这几天思考项目重构的问题,我就啰嗦两句。项目重构说白了就是为controller减负,解耦合。之前项目都是使用mvc模式写的,发现这样写有个弊端,就是一堆代码逻辑都堆积在controller里面,导致有些类文件庞大,有的多达上千行的代码量,阅读起来十分困难,更别说重用了,改个bug都困难。

大家有兴趣的话可以阅读下唐巧的被误解的 MVC 和被神化的 MVVM

站在大牛的肩膀上学习,总是事半功倍的。下面我们来说下MVP架构,插一句,没有任何架构设计是完美的,我们只能给不同的需求制定不同的架构设计,去降低耦合,提高复用。这是MVPDemo,需要的话自行下载。

这是MVP架构设计图,第一次画,有些粗糙
MVP架构图

下面是具体的代码实现:
先来看下类结构


高清无码图

首先来定义一个view的协议,用来处理数据回调,上代码:
#import

@protocol BaseViewProtocol 

- (void)showRemindTitle:(NSString *)message;

@optional
- (void)testTouchAction:(NSInteger)index;
@end

接下来在TabViewController里面去写需求,让P 层执行

@interface TableViewController ()

//V 层包括UIView 和UIViewController及子类,需要持有P 层的实例对象
@property (nonatomic, strong) HomePresenter *presenter;

@end

@implementation TableViewController

- (void)viewDidLoad {
[super viewDidLoad];

//初始化一个P对象
_presenter = [[HomePresenter alloc] init];

//使用协议绑定进行数据传输
_presenter.protocol = self;

//显示head view,这里在P层创建了headView,当然也可以在Controller里面创建,传入P层
self.tableView.tableHeaderView = _presenter.headView;

[_presenter loadData];

}

- (void)showRemindTitle:(NSString *)message{
    if (message) {
      //show view
      [[[UIAlertView alloc] initWithTitle:@"温馨提示" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil] show];
    }
}

MVP中主要代码集中在P层,下面是P层代码逻辑:

@interface HomePresenter ()

@end

/**
 *  P 层作为协调者(中介),需要持有M 层和V 层的对象的引用
 *  适当的时候去协调他们的更新逻辑
 */
@implementation HomePresenter


- (BLoopImageView *)headView{
if (!_headView) {
    _headView = [[BLoopImageView alloc] initWithFrame:CGRectMake(0, 0, Screen_bounds.size.width, 240) delegate:self imageItems:nil isAuto:YES];
}
    return _headView;
}

- (void)setProtocol:(id)protocol{
    _protocol = protocol;
}

- (void)loadData{
    [HomeListModel startGETURL:^(NSArray *info, NSString *error) {
     if (error) {
          //当请求出错时需要回调给出提示信息
          if (self.protocol) {
             [self.protocol showRemindTitle:error];
          }
     } else {
            [self.headView setItemsArr:info];
        }
    }];
}

#pragma mark
- (void)foucusImageFrame:(BLoopImageView *)imageView didSelectItem:(BLoopImageItem *)item{
    NSLog(@"item.title = %@",item.title);
    [self.protocol testTouchAction:item.tag];

}
- (void)foucusImageFrame:(BLoopImageView *)imageView currentItem:(NSInteger)index{
    NSLog(@"index = %zd",index);
}

- (void)cancelHeadView{
    self.headView = nil;
}

M层代码就变得很清爽了,只专一的去做数据处理,并组织好UI 显示的数据,看代码:

@implementation HomeListModel

+ (void)startGETURL:(void (^)(NSArray *info, NSString *error))block{
    [[BKNetworking share] get:@"http://bapi.baby-kingdom.com/index.php?mod=stand&op=index&ver=3.6.0&app=ios" completion:^(BKNetworkModel *model, NSString *netErr) {
        if (netErr) {
            block(nil, netErr);
        } else {
            if (model.status) {
                NSDictionary *data = model.data;
                if ([data isKindOfClass:[NSDictionary class]]) {
                    NSArray *items = [self loadPackageData:data[@"lists"]];
                
                    //创建model
                    block ( items, nil );
                }
            }
        }
    }];
}


//组装数据并返回
+ (NSArray *)loadPackageData:(NSArray *)images{
    //添加最后一张图 用于循环
    int length = (unsigned)images.count;
    NSMutableArray *itemArray = [NSMutableArray arrayWithCapacity:length+2];
    if (length > 1)
    {
        NSDictionary *dict = images[length-1];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:-1];
        [itemArray addObject:item];
    }
    for (int i = 0; i < length; i++)
    {
        NSDictionary *dict = images[i];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:i];
        [itemArray addObject:item];
    }
    //添加第一张图 用于循环
    if (length >1)
    {
        NSDictionary *dict = images[0];
        BLoopImageItem *item = [[BLoopImageItem alloc] initWithDict:dict tag:length];
        [itemArray addObject:item];
    }

    return itemArray;

}

@end

参考文章:

iOS 软件架构 - MVC, MVP, MVVM 和 VIPER 「译」

第一次设计到架构,可能还有问题,希望大家一起交流讨论,谢谢!


你可能感兴趣的:(架构设计之MVP模式)