程序员面试闪充--架构模式
Posted 程序员面试闪充
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序员面试闪充--架构模式相关的知识,希望对你有一定的参考价值。
年年岁岁花相似,岁岁年年人不同。
很久很久以前……
然而随着时间的推移以及技术的发展,传统的MVC模式已经不适合当下的ios开发了。
先让我们来复习一下iOS中的MVC模式吧!
MVC架构模式
在 iOS 开发中,MVC(Model View Controller)是构建iOS App的标准模式。在MVC下,所有的对象被归类为一个Model,一个View,和一个Controller。Model持有数据,View显示与用户交互的界面,而ViewController调解Model和View之间的交互。
现在,MVC 依然是目前主流客户端编程框架。然而,在MVC模式中,厚重的Controller、无以立足的网络逻辑和较差的可测试性已经成为该模式无可避免的问题了。
厚重的Controller
由于大量的代码被放进view controller,导致他们变的相当臃肿。网络数据的请求及后续处理,本地数据库操作,以及一些带有工具性质辅助方法都加大了Massive View Controller的产生。
遗失的网络逻辑
苹果使用的MVC的定义上说,所有的对象都可以被归类为一个model,一个view或是一个controller。那么要把网络的代码放在哪里呢?
显然,不应该把网络请求放在view中。若把它放在model对象里,网络调用应该使用异步,可是这样的话如果一个网络请求比它持有的model生命周期更长,事情就会变得复杂。若是放在contoller里面,也会加剧厚重controller的问题。
较差的可测试性
由于View Controller混合了视图处理逻辑和业务逻辑,分离这些成分的单元测试成了一个艰巨的任务。
为了避免和解决上述问题的产生,于是就从MVC引申出来一种维护性较强、耦合性低的新的架构MVVM(Model View View-Mode),MVVM正式规范了视图和控制器紧耦合的性质,并引入新的组件。MVVM主要目的是为了分离视图(View)和模型(Model)。
MVVM模式
MVVM是Model-View-ViewModel 的简写,最早于2005年被微软的WPF 和 Silverlight的架构师John Gossman提出。
Model:和MVC中的model保持一致,用于处理数据逻辑
View:由 MVC 中的view和 controller 组成,负责 UI 的展示,绑定 viewModel中的属性,触发 viewModel 中的命令以及呈现由viewModel提供的数据。
View-Model:它的职责之一就是作为一个表现视图显示自身所需数据的静态模型,它是从 MVC 的 controller 中抽取出来的展示逻辑,负责从 model中获取 view 所需的数据,转换成 view可以展示的数据,并暴露公开的属性和命令供 view 进行绑定。
在MVVM实现中,利用 RAC来优雅的实现view 和 viewModel 两者之间的数据绑定(同步)。
MVVM优点
1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。
4. 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
MVP模式
MVP是由 MVC演变而来的,它的Presenter根本不用关心ViewController的生命周期,所以在 Presenter里面几乎没有涉及到 UI 的代码,我们所有的 UI 处理全部放到了UIViewController里面,这样的话很符合设计模式中的单一职责。
在MVP中,View和Model之间是不存在引用和依赖的。
下面分享一个MVP架构模式的简单案例。
新建下面的类
在MVPContoller中对三个角色进行关联。
创建属性
controller类需要关联三个角色,因此需要在该类中创建三个角色的属性。
#import "MVPController.h"
#import "MVPView.h"
#import "Presenter.h"
#import "MVPModel.h"
@interface MVPController ()
// 创建三个角色的属性
@property(nonatomic,strong)Presenter* presenter;
@property(nonatomic,strong)MVPView* mvpView;
@property(nonatomic,strong)MVPModel* mvpModel;
@end
对三个角色进行初始化设置
分别创建三个角色,MVPView要添加到Controller上显示。这个案例就是为了将Model的内容显示到view中。所以这里提前给model设置好内容。调用presenter的printTask方法将两者关联起来。
- (void)viewDidLoad {
[super viewDidLoad];
self.mvpView = [MVPView new];
self.mvpModel = [MVPModel new];
self.mvpModel.content = @"line 0";
self.mvpView.frame = self.view.bounds;
[self.view addSubview:self.mvpView];
self.presenter = [Presenter new];
self.presenter.mvpView = self.mvpView;
self.presenter.mvpModel = self.mvpModel;
[self.presenter printTask];
}
model中存储需要的数据,定义内容属性
此处跟mvc不同之处就是给view传递的是一个字符串而不是一个model。因为view与model在mvp架构是无关联的。
@interface MVPModel : NSObject
@property(nonatomic,strong)NSString *content;
@end
在MVPView.h中创建展示view的方法体
@interface MVPView : UIView
-(void)printOnview:(NSString *)content;
@end
在MVPView.m文件中添加按钮
初始化按钮,让model的内容显示在label上。
#import "MVPView.h"
@interface MVPView()
@property(nonatomic,strong)UILabel * label;
@end
@implementation MVPView
-(instancetype)init{
self = [super init];
if(self){
self.backgroundColor = [UIColor orangeColor];
self.label = [UILabel new];
[self addSubview:self.label];
self.label.frame = CGRectMake(30, 100, 300, 30);
self.label.backgroundColor = [UIColor redColor];
self.label.textColor = [UIColor blueColor];
}
return self;
}
-(void)printOnview:(NSString *)content{
self.label.text = content;
}
@end
presenter.h创建一个方法
这个是业务逻辑的入口。
在MVP模式中,所有的耦合都存在与Presenter之中,所以Presenter需要有View和Model的存在。
#import <Foundation/Foundation.h>
#import "MVPModel.h"
#import "MVPView.h"
@interface Presenter : NSObject
@property(nonatomic,strong)MVPView* mvpView;
@property(nonatomic,strong)MVPModel* mvpModel;
- (void)printTask;
@end
将两者通过Presenter联系起来
Prensenter的作用就是调用view并把model的内容传递给它。
-(void)printTask{
NSString *printContent = self.mvpModel.content;
[self.mvpView printOnview:printContent];
}
到程序入口处调用MVPController
#import "ViewController.h"
#import "MVPController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated{
[self showMVP];
}
-(void)showMVP{
MVPController * p = [MVPController new];
[self presentViewController:p animated:YES completion:nil];
}
如此一来,一个简单的MVP案例搭建完毕。
面试题
1、在MVC模式中,如何解决controller层的臃肿问题?
将网络请求抽象到单独的类中
将界面的拼装抽象到专门的类中
构造 ViewModel
这样抽象之后,View 只接受 ViewModel,而 Controller 只需要传递 ViewModel 这么一行代码。而另外构造 ViewModel 的过程,我们就可以移动到另外的类中了
专门构造存储类
2、MVC 和 MVVM 的区别
MVVM是对胖模型进行的拆分,其本质是给控制器减负,将一些弱业务逻辑放到VM中处理
MVC是一切设计的基础,所有新的设计模式都是基于MVC进行的改进。
参考链接:
https://juejin.im/post/59de301cf265da4310475f2c
https://www.jianshu.com/p/db8400e1d40e
https://www.jianshu.com/p/79591e226d8c
以上是关于程序员面试闪充--架构模式的主要内容,如果未能解决你的问题,请参考以下文章