让我们彻底看清MVC、MVP
这里開始记录下来自己对MVC、MVP、MVVM这三种框架模式的理解,本文从以下几个方面来梳理。
- 架构的目的
- 框架模式、设计模式
- MVC设计的介绍
- MVC在Android中的应用
- MVC该怎样设计
- MVP设计的介绍
- MVP在Android中的应用
1. 架构的目的
当我们在进行OOP编程时,一切对象来源于需求,对象结合业务逻辑通过多态、继承、等封装成各个业务模块。我们通过设计将程序模块化,使模块内部高内聚和模块之间低耦合。
这样做的优点是,当我们进行开发或者測试时。我们仅仅须要专注于一点。而不用考虑牵一发动全身之类的问题,从而大大提高了我们的工作效率。可是设计是服务于目的的,就是说我们的需求决定着设计,不同的场景有些不同的需求,那么其应用的设计模式必定是不尽同样的。
万不可为了设计而设计,导致忘记了设计的初衷。
我们举个样例。假使我们的程序仅仅须要实现一个极其简单的功能以至于仅仅有寥寥数行代码,那这时候去考虑引入设计模式是不切实际的。但相反,对于系列庞大、功能众多的app我们就必须考虑引入一套符合情景的模式以梳理开发、简化维护。
2. 框架、设计模式
框架和设计模式是全然的两个概念。框架一般是代码的重用。而设计模式是设计的重用。架构则介于两者之间。部分代码重用,部分设计重用。
可能以上说法比較晦涩难懂。在此摘录一些从业者对它们的理解。
- 框架一般是代码重用,模式是设计重用。
- 设计模式是思考的过程,框架是思考的结果;
- 框架须要用到设计模式。比方我们封装了一套retrofit+okhttp+rxjava网络请求框架,我们可能用到很多设计模式。比方:代理模式、观察者模式等。
- 脱离实际需求谈框架都是耍流氓。
- 框架是面包、面条、饺子…,设计模式是做面包面条饺子的手艺(至于怎么做、做成什么形状、味道…主要看手艺)。
- 设计模式是大量场景总结出来的模版,假设你有对应的场景就能够往上套。
我们今天谈到的MVX系列是框架而不是设计模式。由于MVX框架是用来解决实际需求的(比方View、Model怎样分离相互控制)。
3. MVC设计的介绍
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzM2MjQ0ODY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
MVC的全称是Model View Controller,如图是模型(model)-视图(view)-控制器(controller)的缩写。一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,在改进和个性化定制界面及用户交互的同一时候。不须要又一次编写业务逻辑。
当中M层处理数据。业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。
4. MVC在Android中的应用
我们在文章的最開始说了框架的作用就是为了解决代码的臃肿,提高代码的复用率。在MVC模式中我们能够发现View、Model层都是遵循此原则设计的。
对于View层来讲。我们通常在做一个项目时封装出很多自己定义控件或者动画。封装较好的情况下在别的项目中我们能够直接拿来用,这是View层代码复用的体现。
对于Model层呢?我们能够讲Model理解为用来存储业务数据,当我们的同一app须要跨平台时(比方腾讯视频的apk版和腾讯云极光TV版)我们考虑是不是Model能够共用?
对于Controller层来讲,差点儿不可复用。由于它和业务逻辑联系太紧密。以下我们就来谈谈MVC在android中的体现。
上图为MVC模式在android项目中的体现,View代表视图层。Controller代表控制器。Model代表数据模型,app通过View视图监听控件依据控件表现调用对应的控制器处理业务逻辑,业务逻辑处理完之后控制器通知Model层改变,Model层改变带动View视图变化。
在android中一般採用xml文件进行界面描写叙述,这些xml文件能够视为app的View层,引用很easy,而且通过良好构造也能达到一定的复用性。model对应着各种体现业务逻辑的数据类。它们体现了app的数据(对数据库、网络操作)。而联通它们之间的桥梁就是Controller即Activity、Fragment,我们通过在activity/fragment来管理控制整个业务流程。
这里举个样例来形象地阐述下MVC在Android中的应用,比方一个饭店的做饭流程,做饭就要考虑做什么?拿什么做?这当中是怎样分工的。饭店老板戚总就好比我们的Controller,饭店的厨师老范相当于View(买什么菜他说了算是需求的来源)。採购小王相当于Model。厨师老范须要做个霸王别姬,须要一大堆食材。他把需求报告给戚总,戚总整理成清单要求小王去採购,小王採购完毕后直接将食材交给厨师老范。
这就是MVC的一个循环,当然饭店比較小,有的时候厨师老范仅仅须要一根葱这时候不是必需专门让採购跑一趟了吧也省点油钱。戚总顺手就买了。时间久了,戚总慢慢干了点採购的活…
我们举个简单的样例。
依据学生号码查询其名字、性别、年龄。
V层在xml文件里描写叙述例如以下:
M层数据类例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzM2MjQ0ODY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
C层例如以下:
到这里我们理解了MVC在android中的应用原理,那么我们进一步思考一下。假设app的业务逻辑相对简单,这么负责调控app的activity/fragment中的代码也相对简单。但当处理业务逻辑很繁琐的app时,activity/fragment中的代码就会变得相当臃肿不雅。很不利于维护。而且在实际开发过程中。我们常常在activity/fragment中写下这种代码,例如以下
textView.setText(string);
这样便违反了MVC的原则,在C中处理V,使得C的职责单一性被破坏。所以这时候MVP模型便走进了我们的视野。
下节我们先不讲MVP。当我们知道了MVC的现状后,我们该怎样合理地应用MVC模型。
5. MVC该怎样设计
MVC 尽管仅仅有三层,可是它并没有限制你仅仅能有三层。所以,我们能够将 Controller 里面过于臃肿的逻辑抽取出来,形成新的可复用模块或架构层次。
- 将网络请求抽象到单独的类中;
- 提供自己定义控件封装到专门的类中;
- 构造 ViewModel;
- 专门构造存储类。
通过代码的抽取,我们能够将原本的 MVC 设计模式中的 ViewController 进一步拆分,构造出 网络请求层、ViewModel 层、Service 层、Storage 层等其他类,来配合 Controller 工作,从而使 Controller 更加简单,我们的 App 更easy维护。
另外,不知道大家注意到没,事实上 Controller 层是很难于測试的。假设我们能够将 Controller 瘦身,就能够更方便地写 Unit Test 来測试各种与界面的无关的逻辑。
移动端自己主动化測试框架都不太成熟,可是将 Controller 的代码抽取出来。是有助于我们做測试工作的。
6. MVP设计的介绍
还记得我们上面的饭店吧。时间久了戚总有时候为了多省点油钱越来越多的担任採购的活了,甚至还兼职抄起了菜…慢慢的随着饭店的生意越来越好慢慢做大。戚总的事情越来越多開始忙只是来了。还有一方面饭店的生意好了却不见得多挣了多少钱。戚总想着会不会是厨师老范和採购小王串通坑他呢,于是乎。戚总想了一夜,哎嗨,一套新的管理机制来了。
View还是厨师老范,Model是採购小王,戚总把自己定位为Presenter,以后厨师老范有需求了仍然告诉戚总,戚总安排给小王去採购,採购完之后把食材交给戚总检查,数目账单没问题了戚总再将食材给厨师老范。这样不让厨师老范和採购小王就没有不论什么机会沟通避免他们串通。同一时候戚总以后仅仅负责吩咐两人做事也不为了省点油钱自己亲自干了毕竟生意做大了得像个老板的样子了,由此MVP模型初见雏形。
其示意图例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzM2MjQ0ODY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
这样做它有何利弊呢?我们仍然结合饭店的样例加以说明。
首先使它的优点:
- 分工明白,大家各司其职就好提高效率;
- 利于以后的发展。比方要裁人换人等,像MVC模式我假设换掉厨师,就会同一时候影响老板和採购的工作。MVP呢不管怎样调整我们仅仅调整P即可,其他模块互不干涉影响。
- 大大解放老板的工作(是P层支付者调度降低代码臃肿)。
- 用程序语言就是更加高内聚、低耦合;
再来谈谈它的弊端:
- 结构复杂了。
整体而言。对于业务逻辑复杂的项目,MVP的利要远大于弊。
7. MVP在Android中的应用
以下我们就来谈谈MVP在Android之中的应用,既然是在Android中的应用,那么我们就考虑从大哥那儿学一套本事%>_<%。
这是Google大哥的官方demo。
再来一篇分析demo的文章。
研究完了上面的,我们是时候来点实践了。就模拟个登录功能吧。
首先看清文件结构:
google应用了BaseView、BasePresenter两个类。 例如以下:
这两个类作为全部view和presenter的基类来使用。
BasePresenter中的start方法是用来load页面时载入对应数据的。而登录模块临时并不须要该方法,可是这个类毕竟是为整个业务模块服务的。别的业务可能须要。临时保留。
BaseView中的setPresenter方法是为了向fragment中传递activity中new出来的presenter对象。登录模块事实上一个activity足以搞定,这种方法多余。可是保留该方法。理由同上。
開始详细业务。这里须要构建view和presenter。值得注意的点是。google将view和presenter放到了一个契约类中了。
所以
View中提供了四个相关操作,即登录成功、登录失败、获取username、获取密码。
Presenter中仅仅提供了login()登录操作。
这里activity作为mvp中的view层实现了契约类中的view接口。
public class LoginActivity extends Activity implements LoginContract.View{
private Context mContext;
private EditText mNameEt, mPasswordEt;
private Button mLoginBtn;
private LoginContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
mContext = this;
mPresenter = new LoginPresenter(this);
mNameEt = (EditText) findViewById(R.id.nameEt);
mPasswordEt = (EditText) findViewById(R.id.passwordEt);
mLoginBtn = (Button) findViewById(R.id.loginBtn);
mLoginBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.login();
}
});
}
@Override
public void loginSuccess() {
Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
}
@Override
public void loginFailed() {
Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
}
@Override
public String getLoginName() {
return mNameEt.getText().toString();
}
@Override
public String getLoginPassword() {
return mPasswordEt.getText().toString();
}
@Override
public void setPresenter(Object presenter) {
}
}
注意,假设你是fragment作为view,一定要加上mView.setPresenter(this)把P传递过去。
public class LoginPresenter implements LoginContract.Presenter{
private LoginContract.View mView;
public LoginPresenter(LoginContract.View view){
mView = view;
}
@Override
public void login() {
boolean successFlag = httpLogin(mView.getLoginName(), mView.getLoginPassword());
if ( successFlag )
mView.loginSuccess();
else
mView.loginFailed();
}
@Override
public void start() {
}
}
Google通过一个契约类使我们的项目结构更加清晰。
当然没有绝对的MVP、MVC框架。比方在上面的登录功能中我们利用MVC更加方便简单。可是假设考虑以后的扩展性(比方添加第三方登录等等)利用MVP更加合适。
所以不管选择哪种方式必定是建立在需求的基础上的。
好了,临时告一段落吧…
让我们彻底看清MVC、MVP的更多相关文章
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...
- MVC, MVP, MVVM比较以及区别(下)
上一篇得到大家的关注,非常感谢.一些朋友评论中,希望快点出下一篇.由于自己对于这些模式的理解也是有限,所以这一篇来得迟了一些.对于这些模式的比较,是结合自己的理解,一些地方不一定准确,但是只有亮出自己 ...
- android MVC && MVP && MVVM分析和对比
相关:http://www.cnblogs.com/wytiger/p/5305087.html 出处http://blog.csdn.net/self_study,对技术感兴趣的同鞋加群544645 ...
- MVC, MVP, MVVM比较以及区别
MVC, MVP和MVVM都是用来解决界面呈现和逻辑代码分离而出现的模式.以前只是对它们有部分的了解,没有深入的研究过,对于一些里面的概念和区别也是一知半解.现在一边查资料,并结合自己的理解,来谈一下 ...
- 从.NET的宠物商店到Android MVC MVP
1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次知道QA和SQA的区别.Training Project时 ...
- Android MVC MVP
从.NET的宠物商店到Android MVC MVP 1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次 ...
- [转]从三层架构到MVC,MVP
本来是不想跳出来充大头蒜的,但最近发现园子里关于MVC的文章和讨论之风越刮越烈,其中有些朋友的观点并不是我所欣赏和推荐的,同时最近也在忙着给公司里的同事做MVC方面的“扫盲工作”.所以就搜集了一些大家 ...
- 前端mvc mvp mvvm 架构介绍(vue重构项目一)
首先 我们为什么重构这个项目 1:我们现有的技术是前后台不分离,页面上采用esayUI+jq构成的单页面,每个所谓的单页面都是从后台胜场的唯一Id 与前端绑定,即使你找到了那个页面元素,也找不到所在的 ...
- 架构 MVC MVP MVVM 简介 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
随机推荐
- BZOJ3875: [Ahoi2014&Jsoi2014]骑士游戏
[传送门:BZOJ3875] 简要题意: 给出n种怪物,每种怪物都带有三个值,S[i],K[i],R[i],分别表示对他使用普通攻击的花费,使用魔法攻击的花费,对他使用普通攻击后生成的其他怪物. 每种 ...
- Android Support Library 23.2用法简析
写在前面的几句话 前几天谷歌发布了android-support-library-23.2支持库,这一次23.2版本增加了一些新的支持库以及新的功能.接下来这篇文章,就是对这些新功能部分做简单的用法介 ...
- “DNS隧道”盗号木马分析——类似hjack偷密码然后利用dns tunnel直传数据发送出去
摘自:http://www.freebuf.com/articles/network/38276.html# 运行后不断监控顶端窗口,一旦发现为QQ,就弹出一个自己伪造的QQ登陆窗口,诱导用户输入密码 ...
- 访问API的方式为:localhost/api/customers, 创建自定义JSON格式化器
注意的是,访问API的方式为:localhost/api/customers,在实际中将要根据情况替换合适的端口,默认所有的WEB API都是通过/api根目录的方式访问的 创建自定义JSON格式化器 ...
- WebAssembly学习(五):AssemblyScript - Hello World
一.项目创建 1.创建AssemblyScript根目录 mkdir AssemblyScript 2.安装AssemblyScript开发依赖 cnpm install --save-dev Ass ...
- vue踩坑-This relative module was not found
在使用vue.js的日期选择插件 的时候,报错如下 This relative module was not found: * ../calendar.vue in ./node_modules/ba ...
- Spring MVC 转发和重定向
本文介绍Spring MVC中转发和重定向的区别. 转发和重定向 开始Java EE时,可能会对转发(forward)和重定向(redirect)这个两个概念不清楚.本文先通过代码实例和运行结果图片感 ...
- 洛谷—— P2387 魔法森林
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- jquery10 闭包示例
o = { a:1, o:{ b:2, f : function(){ alert(o.a); alert(o.b);//undefined } } } o.o.f(); o = { a:7, o : ...
- amaze ui使用简介
amaze ui使用简介 amaze UI 类似于bootstrap 不过比bootstrap更加轻量级 可以用来开发响应式网站,并且是移动优先的,针对移动设备开发的网站可以考虑使用这个框架 css中 ...