最近在想写有关架构模式的博客,想了下目前自己接触的过就比较简单的就是MVP,MVC,其他比如MVVM什么的只是初步的了解一下,并没有实际的
去实践过.
以前刚开始做Android的时候是做外包的,也是一边学一边写,架构模式什么的听说过,没实际写过,后面写了一两个之后,感觉很多地方都是在做
重复劳动,有些新需求改动什么的,要从以前写的茫茫多的代码里面找到相应的地方修改,还不止改一个地方,哎,自己挖坑自己填.后来就开始逐渐
使用架构模式,最初的是mvc,最近开始使用mvp.
说实在的,我们使用架构模式,是为了去实现那句"模块内部高聚合,模块之间低耦合",在使用过程中,开发效率的确能得到不少的提升,并且能方便
功能测试以及定位问题.
但是,切忌不要为了架构而去架构,架构的初衷是为了提高效率以及为后续提供便捷,如果一个项目只有简单的几个java文件,而你还兴高采烈的
去引入框架或者架构,将本来只需要做点功能模块划分的工作变得复杂,这就得不偿失了.
所以,对于不同量级的工程,要区别对待,同时在制定架构的同时也要和后台人员沟通协作好,毕竟团队协作,是一个项目能更好的完成的
必不可少的条件之一.
聊到这里就差不多了,作为一个程序员的博客,怎么能只有文字没有代码呢?稍等,还有几行目录,看完就贴点代码,配合代码看起来更直观,方便理解.
- 1.mvc
- 1.1 mvc简介
- 1.2 mvc在Android中的应用
- 2.mvp
- 2.1 mvp简介
- 2.2 mvp在Android中的应用
- 3.mvc与mvp的异同
1.MVC
1.1MVC简介
说道mvc大家肯定都很熟悉,model(模型)-view(视图)-controller(控制器).原理么简单说一下:
1.View传送指令到Controller
2.Controller完成业务逻辑,要求Model更改状态
3.Model将新的数据发送到View,用户得到反馈
所有通信都是单项的.
这个图相信大家看过很多遍了吧,再看一遍加深下印象.
1.2MVC在Android中的应用
先上2个效果图.
贴上代码
/**
* Controller&View
*/
public class MainActivity extends Activity implements onResultListener {
private EditText mInput;
private TextView mResult;
private UserModelImpl mUserImpl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserImpl = new UserModelImpl();
init();
}
/**
* 初始化布局
*/
private void init() {
mInput = (EditText) findViewById(R.id.input_text);
mResult = (TextView) findViewById(R.id.tv_result);
}
/**
* button 点击事件
* @param view
*/
public void doMain(View view) {
mUserImpl.getData(mInput.getText().toString(), this);
}
/**
* 将结果打印出来
* @param result
*/
public void showResult(String result) {
mResult.setText(result);
}
@Override
public void onSuccess(String result) {
showResult(result);
}
@Override
public void onFail() {
mResult.setText("这里只有hong,ling,jin,没有其他人");
}
}
/**
* Model模型
*/
public interface DataModel {
void getData(String text,onResultListener listener);
}
.................
public class UserModelImpl implements DataModel {
@Override
public void getData(String text, onResultListener listener) {
//这里偷懒下,我写点假数据,假装我是从别的地方获取数据的
List<User> users = UserData.getData();
boolean isExist = false;
for (int i = 0; i < users.size(); i++) {
//判断传入的人名是否存在
if (text.equals(users.get(i).getName())) {
listener.onSuccess(users.get(i).toString());
isExist = true;
}
}
if (!isExist) {
listener.onFail();
}
}
}
从上面代码可以看出Activity持有了UserModel对象,当用户点击button之后,Activity作为控制层从View层的EditText中获得数据,
然后向Model层发送数据请求,处理完毕之后,通过onResultListener通知View层数据处理完毕并更新UI页面.整体MVC框架
就在Activity中体现出来了.
稍微去关注下Model层那段代码,这里有一个DataModel模型接口,一个实现了该接口的UserModelImpl类.Activity控制器通过调用
UserModelImpl中的getData方法处理数据,后通过onResultListener返回结果,通知View层刷新页面.
讲句明白话,这里Activity将View层的显示以及Model的数据处理给隔开了,也就是说activity担当controller很好的完成了model和view
之间的协调工作.
2.MVP
2.1MVP简介
MVP是从更早的MVC框架演变而来的,与MVC有一定的相似性:
View负责绘制UI,与用户进行交互.
Model负责处理数据.
Presenter作为view和model交互的中间纽带,处理与用户交互的逻辑.
另外此模式下还有些特性:
1、模型与视图完全分离,我们可以修改视图而不影响模型;
2、更高效地使用模型,因为所有的交互都发生在Presenter内部;
3、Presenter可以在不修改逻辑的前提下,多次复用.
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。
说到这里,举个简单的例子:
UI层通知逻辑层(Presenter)用户点击了一个Button,逻辑层(Presenter)自己决定应该用什么行为进行响应,
该找哪个模型(Model)去做这件事,最后逻辑层(Presenter)将完成的结果更新到UI层。
2.2 MVP在Android中的应用
这个是此框架在app中的包结构图:
建立Bean:
public class UserBean {
private String mFirstName;
private String mLastName;
public UserBean(String mFirstName, String mLastName) {
this.mFirstName = mFirstName;
this.mLastName = mLastName;
}
public String getmFirstName() {
return mFirstName;
}
public String getmLastName() {
return mLastName;
}
}
建立model:
public interface IUserModel {
void setID(int id);
void setFirstName(String firstName);
void setLastName(String lastName);
int getID();
UserBean load(int id);//根据id去查用户信息
}
这个是model 的接口,实现就不写了,自己新建个java文件实现这个接口即可.
Presenter:通过Model,IView的接口来操作view和model,activity将所有逻辑交给presenter来处理.
public class UserPresenter {
private IUserView mUserView;
private IUserModel mUserModel;
public UserPresenter(IUserView view) {
this.mUserView = view;
mUserModel = new UserModel();
}
public void saveUser(int id,String firstName,String lastName){
mUserModel.setID(id);
mUserModel.setFirstName(firstName);
mUserModel.setLastName(lastName);
}
public void loadUser(int id){
UserBean bean = mUserModel.load(id);
mUserView.setFirstName(bean.getmFirstName());
mUserView.setLastName(bean.getmLastName());
}
}
View:列出了当前view所需要的操作方法,也是个接口
public interface IUserView {
int getID();
String getFirstName();
String getLastName();
void setFirstName(String firstName);
void setLastName(String lastName);
}
activity实现了IView接口,并在其中操作view,实例化了一个presenter对象.
public class MainActivity extends Activity implements IUserView {
private UserPresenter mPresenter;
private EditText mInputId, mInputFirst, mInputLast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);
init();
mPresenter = new UserPresenter(this);
}
private void init() {
mInputId = (EditText) findViewById(R.id.input_id);
mInputFirst = (EditText) findViewById(R.id.input_firstname);
mInputLast = (EditText) findViewById(R.id.input_lastname);
}
public void doSave(View view) {
mPresenter.saveUser(getID(), getFirstName(), getLastName());
}
public void doLoad(View view) {
mPresenter.loadUser(getID());
}
@Override
public int getID() {
return new Integer(mInputId.getText().toString());
}
@Override
public String getFirstName() {
return mInputFirst.getText().toString();
}
@Override
public String getLastName() {
return mInputLast.getText().toString();
}
@Override
public void setFirstName(String firstName) {
mInputFirst.setText(firstName);
}
@Override
public void setLastName(String lastName) {
mInputLast.setText(lastName);
}
}
刚开始看肯定不明白这个是什么,为什么要这样写,我就这么点代码还要分那么多文件?
首先,刚开始看到这模式的确会有点不适应,刚接触新事物嘛,如果不会,照着上面这个例子自己写一遍,再好好体会一下.
其次,上面只是个例子,方便初步理解一下mvp到底长什么样子,说了那么多还是要看代码才能一目了然.
还有就是先实现功能,再考虑代码重构,一直在那边思考代码到底臃肿不臃肿,用什么方式去写,不知道什么时候才能写好.
MVC与MVP的异同
先说一下共同点,也是最直观的,就是View和Model:
- Model模型–数据对象,提供本应用对外部应用程序数据操作的接口,也可以在内部数据发生变化时发出通知的,而且本身不依赖于View,可以通过调用接口来对数据进行操作.
- View视图–UI层,提供给用户操作功能以及以及展现UI页面和一些相关的逻辑操作.
两种模式的主要区别:
mvc的时候,view可以和model直接交互,不能做到真正的低耦合,如果代码量一大,则会在activity里面越写越多,到后面自己都不想去看那些写的奇奇怪怪的代码了.
而map下,View与Presenter是一对一的,如果你的view很复杂的话,可以绑定多个Presenter来处理逻辑,并且他们之间是通过接口来进行交互的,可以很方便的添加单元测试.
结语
最后提一下MVVM,MVVM可以算是MVP的升级版,这可不是Model,View,View,Model4个元素混在一起,后面2个VM是ViewModel的缩写.ViewModel可以理解成为是View和Presenter的合体,ViewModel和View之间的交互式通过DataBinding完成的,而且DataBinding可以实现双向交互,进一步的降低view和model之间的耦合程度.
还有在我们实际使用的时候,不必纠结到底使用哪个模式好,选择恐惧症的毛病犯起来可得浪费不少时间,只要能更方便快捷实现项目需求,那就是最适合的架构,不必在意是否过时.