上篇文章讲了内存管理,这篇文章主要讲解关于架构的一些思考,通过这篇文章你将了解到
- MVC
- MVC变种
- MVP
- MVVM
- 分层设计的优缺点
没有最好的架构,只有最适合业务的架构。
MVC
苹果版本的MVC
是Model
和VC
和交互,VC
和View
交互
-
优点:
View
和Model
可以重复利用,可以独立使用 -
缺点:
Controller
的代码过于臃肿
代码:
- (void)viewDidLoad {
[super viewDidLoad];
[self loadData];
}
- (void)loadData{
self.data=[NSMutableArray array];
for (int i = 0; i < 20; i ++) {
FYNews *item=[FYNews new];
item.title =[NSString stringWithFormat:@"title-%d",i];
item.name =[NSString stringWithFormat:@"name-%d",i];
[self.data addObject:item];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
// Configure the cell...
FYNews *item =[self.data objectAtIndex:indexPath.row];
cell.detailTextLabel.text =item.title;
cell.textLabel.text = item.name;
return cell;
}
//model
@interface FYNews : NSObject
@property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *name;
@end
这里是VC
中组装了tableview
,model
的数据在VC
中在view
中显示出来,当需要另外的数据的时候,只需要将model
改成需要的model
而无需更改tableview
的代码兼容性较好。
MVC变种
MVC
变种,其实就是将model
和view
建立了联系,view
依据Model
来展示数据,VC
组装Model
,组装展示是在view
中实现。
-
优点:对Controller进行瘦身,将View的内部细节封装起来了,外界不知道View内部的具体实现
-
缺点:view依赖于Model
代码实现
//.h
@class FYItemModel;
@interface FYAppleView : UIView
@property (nonatomic,strong) FYItemModel *model;
@end
//.m
@interface FYAppleView()
@property (nonatomic,strong) UILabel *nameLabel;
@end
@implementation FYAppleView
-(instancetype)initWithFrame:(CGRect)frame{
if (self =[super initWithFrame:frame]) {
_nameLabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
[self addSubview:_nameLabel];
}
return self;
}
/* mvc的变种 */
- (void)setModel:(FYItemModel *)model{
_model = model;
_nameLabel.textColor = model.bgColor;
_nameLabel.text = model.name;
}
@end
//FYItemModel
@interface FYItemModel : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,strong) UIColor *bgColor;
@end
//ViewController
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self loadViewOtherMVC];
}
//变种MVC 把View和Model建立起连接
//等以后更新view数据只需要 view.model = item;Controllr少了许多代码
- (void)loadViewOtherMVC{
FYAppleView * view =[[FYAppleView alloc]initWithFrame:CGRectMake(200, 200, 100, 30)];
FYItemModel *item=[[FYItemModel alloc]init];
item.name = @"校长来了";
item.bgColor = [UIColor redColor];
view.model = item;
[self.view addSubview:view];
}
@end
可以看到model
组装到view
展示内容是在view
实现的,外部不知道细节,只需要将model
给view
即可,但是只能传输过来model
或者他子类,业务更改的话,需要修改view
的内部model
才能将变更过的数据重新展示出来。
想要监听view的点击事件来做一些操作,那么我们可以使用代理和block
,这里id
是实现了FYAppleViewProtocol
协议的,weak
修饰防止循环引用,使用协议实现了和VC
的通信。
@class FYAppleView;
@protocol FYAppleViewProtocol <NSObject>
- (void)FYAppleViewDidClick:(FYAppleView*)view;
@end
@class FYItemModel;
@interface FYAppleView : UIView
@property (nonatomic,strong,readonly) UILabel *nameLabel;
@property (nonatomic,weak) id<FYAppleViewProtocol> delegate;
@property (nonatomic,strong) FYItemModel *model;
@end
稍作更改还是apple-MVC
// .h
@class FYItemModel;
@interface FYAppleView : UIView
@property (nonatomic,strong,readonly) UILabel *nameLabel;
@end
将View
属性nameLabel
暴露出来,但是不允许外界进行更改,去掉model
则是MVC
。
MVP
MVP
和MVC
很像,只是将VC
换成了Presenter
,vc
和Present
做的事情基本一致,将view
和Model
通信改到了都和Presenter
通信。
代码
//MVP
//.h
@interface FYNewsPresenter : NSObject
@property (nonatomic,weak) UIViewController *vc;
//初始化
- (void)setup;
@end
.m
#import "FYNewsPresenter.h"
@interface FYNewsPresenter()<FYAppleViewProtocol>
@end
@implementation FYNewsPresenter
- (void)setup{
FYAppleView * view =[[FYAppleView alloc]initWithFrame:CGRectMake(200, 200, 100, 30)];
FYItemModel *item=[[FYItemModel alloc]init];
item.name = @"校长来了";
item.bgColor = [UIColor redColor];
view.model = item;
[self.vc.view addSubview:view];
}
- (void)FYAppleViewDidClick:(FYAppleView *)view{
NSLog(@"点击了我");
}
@end
//VC中
@interface ViewController ()
@property (nonatomic,strong) FYNewsPresenter *presenter;
@end
- (void)viewDidLoad {
[super viewDidLoad];
_presenter=[FYNewsPresenter new];
_presenter.vc = self;
[_presenter setup];
}
@end
再次对VC
进行了瘦身,将更多的业务逻辑搬到了FYNewsPresenter
处理,其实全部搬过去,意义比不大,FYNewsPresenter
也会臃肿,也会出现和VC
一样的困惑。
MVVM
MVVM
是将FYNewsPresenter
都搬到了FYNewsViewModel
中,然后对FYNewsViewModel
和View
进行了一个双向绑定,双向绑定可以使用代理,block
或者KVO
实现。
代码实现
@interface FYNewsViewModel : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,strong) UIColor *bgColor;
@property (nonatomic,weak) UIViewController *vc;
- (instancetype)initWithController:(UIViewController *)vc;
@end
#import "FYNewsViewModel.h"
@interface FYNewsViewModel()<FYAppleViewProtocol>
@end
@implementation FYNewsViewModel
- (instancetype)initWithController:(UIViewController *)vc{
if (self =[super init]) {
self.vc = vc;
FYAppleView * view =[[FYAppleView alloc]initWithFrame:CGRectMake(100, 200, 100, 50)];
// view.model = item;
view.delegate = self;
view.viewModel = self; //建立kvo
view.backgroundColor = [UIColor lightGrayColor];
[vc.view addSubview:view];
FYItemModel *item=[[FYItemModel alloc]init];
item.name = @"校长来了";
item.bgColor = [UIColor redColor];
self.name = item.name;
self.bgColor = item.bgColor;
}
return self;
}
- (void)FYAppleViewDidClick:(FYAppleView *)view{
NSLog(@"点击了我");
}
@end
在view
实现
@class FYAppleView,FYNewsViewModel;
@protocol FYAppleViewProtocol <NSObject>
- (void)FYAppleViewDidClick:(FYAppleView*)view;
@end
@class FYItemModel;
@interface FYAppleView : UIView
@property (nonatomic,strong,readonly) UILabel *nameLabel;
@property (nonatomic,weak) id<FYAppleViewProtocol> delegate;
@property (nonatomic,weak) FYNewsViewModel *viewModel;
@property (nonatomic,strong) FYItemModel *model;
@end
@interface FYAppleView()
@property (nonatomic,strong) UILabel *nameLabel;
@end
@implementation FYAppleView
-(instancetype)initWithFrame:(CGRect)frame{
if (self =[super initWithFrame:frame]) {
_nameLabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
[self addSubview:_nameLabel];
}
return self;
}
/* mvc的变种 */
- (void)setModel:(FYItemModel *)model{
_model = model;
_nameLabel.textColor = model.bgColor;
_nameLabel.text = model.name;
}
- (void)setViewModel:(FYNewsViewModel *)viewModel{
_viewModel = viewModel;
[_viewModel addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//使用FBKVO实现 或者自己使用KVO实现
// __weak typeof(self) waekSelf = self;
// [self.KVOController observe:viewModel keyPath:@"name"
// options:NSKeyValueObservingOptionNew
// block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
// waekSelf.nameLabel.text = change[NSKeyValueChangeNewKey];
// }];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"name"]) {
self.nameLabel.text = change[NSKeyValueChangeNewKey];
}
}
//添加点击事件
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if ([self.delegate respondsToSelector:@selector(FYAppleViewDidClick:)]) {
[self.delegate FYAppleViewDidClick:self];
}
}
-(void)dealloc{
[_viewModel removeObserver:self forKeyPath:@"name"];
}
@end
使用KVO
或者FBKVO
或者RAC
都是可以的,本章节例子给出了FBKVO
或者自己使用KVO
的实现。
分层设计
三层架构:
三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层
-
目的: “高内聚,低耦合”的思想
-
优点: 降低层与层之间的依赖 标准化
-
缺点: 系统架构复杂,不适合小型项目
三层原理
3个层次中,系统主要功能和业务逻辑都在业务逻辑层进行处理。 所谓三层体系结构,是在客户端与数据库之间加入了一个
中间层
,也叫组件层。这里所说的三层体系,不是指物理上的三层,不是简单地放置三台机器就是三层体系结构,也不仅仅有B/S
应用才是三层体系结构,三层是指逻辑上的三层,即把这三个层放置到一台机器上。
三层体系的应用程序将业务规则、数据访问、合法性校验等工作放到了中间层进行处理。通常情况下,客户端不直接与数据库进行交互,而是通过
COM/DCOM
通讯与中间层建立连接,再经由中间层与数据库进行交互。
三层架构中主要功能与业务逻辑一般要在业务逻辑层进行信息处理和实现,其中三层体系架构中的客户端和数据库要预设中间层,成为组建层。三层架构中的三层具有一定的逻辑性,即是将三层设置到同一个计算机系统中,把业务协议、合法校验以及数据访问等程序归置到中间层进行信息处理,一般客户端无法和数据库进行数据传输,主要是利用
COM/DCOM
通讯和中间层构建衔接通道,实现中间层与数据库的数据传输,进而实现客户端与是数据库的交互
MVC
、MVVM
、MVP
属于界面层, 当业务复杂,网络请求和db操作达到了一个新的高度,界面复杂到需要好多人来做,那么界面、业务、数据需要分层了
分层之后,得到了一个三层架构或四层架构
数据层也可以分为两层,分为网络请求和db层。
具体在工程中我们通常这样体现
在vc
中获取数据
@interface ViewController ()
@property (nonatomic,strong) FYDBPool *db;
@property (nonatomic,strong) FYHttpPool *http;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//当有业务层
[[FYNewsService new] loadNewsWithInfo:nil success:^(NSArray * _Nonnull) {
} fail:^{
}];
//当没有有业务层
self.db=[FYDBPool new];
self.http=[FYHttpPool new];
[self.db loadNewsWithInfo:@{} success:^(NSArray * _Nonnull ret) { if ([ret count]) {
NSLog(@"数据获取成功");
}else{
[self.http loadNewsWithInfo:@{} success:^(NSArray * _Nonnull ret) { NSLog(@"数据获取成功"); } fail:^{ NSLog(@"数据获取失败"); }];
}
} fail:^{
[self.http loadNewsWithInfo:@{} success:^(NSArray * _Nonnull ret) {
NSLog(@"数据获取成功");
} fail:^{
NSLog(@"数据获取失败");
}];
}];
}
在业务层
@interface FYNewsService ()
@property (nonatomic,strong) FYDBPool *db;
@property (nonatomic,strong) FYHttpPool *http;
@end
@implementation FYNewsService
-(instancetype)init{
if (self = [super init]) {
self.db=[FYDBPool new];
self.http=[FYHttpPool new];
}
return self;
}
- (void)loadNewsWithInfo:(NSDictionary *)info
success:(succcessCallback )succblock
fail:(dispatch_block_t)failBlock{
[self.db loadNewsWithInfo:info success:^(NSArray * _Nonnull ret) { if ([ret count]) {
succblock(ret);
}else{
[self.http loadNewsWithInfo:info success:^(NSArray * _Nonnull ret) { succblock(ret); } fail:failBlock];
}
} fail:^{
[self.http loadNewsWithInfo:info success:^(NSArray * _Nonnull ret) {
succblock(ret);
} fail:failBlock];
}];
}
@end
在db层
typedef void(^succcessCallback)(NSArray *);
@interface FYDBPool : NSObject
- (void)loadNewsWithInfo:(NSDictionary *)info
success:(succcessCallback )succblock
fail:(dispatch_block_t)failBlock;
@end
在网络请求层
typedef void(^succcessCallback)(NSArray *);
@interface FYHttpPool : NSObject
- (void)loadNewsWithInfo:(NSDictionary *)info
success:(succcessCallback )succblock
fail:(dispatch_block_t)failBlock;
@end
分层目的是瘦身,逻辑清晰,业务清晰,降低耦合,当某一块足够复杂时候,都可以进行分层,不局限于网络或db
,当db
足够复杂,也需要进行一个分层来解决复杂调用和处理的问题。 不同的人来处理不同的分层,相互影响也比较小,降低耦合。
当逻辑层足够完善,则UI层如何变动都不需要更改逻辑层。
后记
优雅的代码总是伴随着各种传统设计模式的搭配
设计模式
设计模式(Design Pattern) 是一套被反复使用、代码设计经验的总结 使用设计模式的好处是:可重用代码、让代码更容易被他人理解、保证代码可靠性 一般与编程语言无关,是一套比较成熟的编程思想
设计模式可以分为三大类
-
创建型模式:对象实例化的模式,用于解耦对象的实例化过程 单例模式、工厂方法模式,等等
-
结构型模式:把类或对象结合在一起形成一个更大的结构 代理模式、适配器模式、组合模式、装饰模式,等等
-
行为型模式:类或对象之间如何交互,及划分责任和算法 观察者模式、命令模式、责任链模式,等等
总结
- 适合项目的才是最好的架构
资料参考
资料下载
最怕一生碌碌无为,还安慰自己平凡可贵。
广告时间
今天的文章iOS底层原理 MVC、MVP、MVVM、分层设计浅谈 — (13)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/19946.html