画出这三种开发模式的设计图,并给出它们的适用场景和优缺点。
一、MVC
1、MVC简介
MVC是Model View Controller的缩写,是一种典型的设计开发模式。其中Model为模型,View为视图,Controller为控制器。它的模式设计图如下所示:
MVC开发模式设计图
它的工作流程是这样的:
View接收用户的请求操作
View将用户的请求操作传递给Controller
Controller操作Model进行数据的更新
Mode在数据更新完毕后通知View进行界面刷新
从上面的工作流程可以得知,Controller持有了View和Model对象,Model持有View对象。
在Android中,View对应着xml布局文件,Model对应着实体模型(网络、数据库、IO等),Controller对应着Activity的业务处理,数据处理,UI展示等逻辑。在实际开发过程中,xml作为View层,能够实现的功能实在是太弱,所以一般我们会将Activity作为View和Controller。
2、MVC的一个例子
我们通过一个例子来看一下MVC模式的工作流程:
现在我们要点击上面“寻找图书”的按钮,然后在下面可以得到图书信息。上图就是xml的布局。
我们先看一下Model层:
package com.example.runningh.mydemo.testmvc;
/**
* Created by hwldzh on 2018/6/12
* 类描述: Model层
*/
public class Book {
private SearchBookActivity activity;
private int price = 100;
private String bookName = "Android艺术开发探索";
public Book(SearchBookActivity activity) {
this.activity = activity;
}
public void findBook() {
activity.updateView(this);
}
public String toString() {
return "bookName=" + bookName + "; bookPrice=" + price;
}
}
Controller层:
package com.example.runningh.mydemo.testmvc;
/**
* Created by hwldzh on 2018/6/12
* 类描述: Controller层
*/
public class ControllerBook {
private SearchBookActivity activity;
public ControllerBook(SearchBookActivity activity) {
this.activity = activity;
}
public void findBook() {
Book book = new Book(activity);
book.findBook();
}
}
View层:
package com.example.runningh.mydemo.testmvc;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.TextView;
import com.example.runningh.mydemo.R;
/**
* Created by hwldzh on 2018/6/12
* 类描述: View层
*/
public class SearchBookActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_book);
final ControllerBook controllerBook = new ControllerBook(this);
findViewById(R.id.find_books).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
controllerBook.findBook();
}
});
}
public void updateView(Book book) {
TextView bookInfoView = findViewById(R.id.book_info_view);
bookInfoView.setText(getString(R.string.book_info, book.toString()));
}
}
可以看到在View层中(SearchBookActivity)通过按钮的点击事件,触发Controller层(ControllerBook)的findBook方法,在Controller层的findBook方法中调用了Model层(Book)的findBook方法,在Model层获得Book数据后,将该数据传递给View层(通过调用SearchBookActivity的updateView方法),然后在updateView方法中对View进行更新。
3、优缺点
- 优点:
模块化的程度很高,各层负责完成不同的逻辑处理。 - 缺点:
在Android实际开发中,MVC开发模式中的Activity既要负责View层的更新,同时也负责Controller层对逻辑的控制,如果一个功能比较复杂,那么Activity要承担的任务就非常繁重,导致Activity的代码量非常庞大。
Mode层和View层之间存在着耦合关系。
4、适用场景
由上面MVC的优缺点可以得知,MVC开发模式适合运用在一些功能比较简单的,业务逻辑比较少的小型项目中。
二、MVP
1、MVP简介
MVP是Model View Presenter的缩写。其中Model为模型,ViewWie视图,Presenter为桥接器。针对MVC设计模式中Activity的工作量巨大,代码逻辑比较复杂等缺点进行了一定的改进,将代码控制逻辑单独拆分开,放在Presenter模块。它的模式设计图如下所示:
MVP开发模式设计图
它的工作流程是这样的:
View接收用户的请求操作
View将用户的请求操作传递给Presenter
Presenter操作Model进行数据的更新
Model在数据更新完毕后回调给Presenter
Presenter在拿到更新的数据后将数据回调给View
View进行界面的刷新
在Android中,View对应着xml布局文件和Activity,Model对应着实体模型(网络、数据库、IO等),Presenter作为View和Model两者之间的桥梁,对业务逻辑进行操控,这样就将View和Model进行了解耦,它们两者都由Presenter进行逻辑之间的操控。
2、MVP的一个例子
还是上面的例子,我们将其修改为MVP模式。
我们先看一下Model层:
package com.example.runningh.mydemo.testmvc;
/**
* Created by hwldzh on 2018/6/12
* 类描述: Model层
*/
public class Book {
private OnFindBookListener mListener;
private int price = 100;
private String bookName = "Android艺术开发探索";
public Book(OnFindBookListener listener) {
this.mListener = listener;
}
public void findBook() {
String bookInfo = "bookName=" + bookName + "; bookPrice=" + price;
mListener.onSuccess(bookInfo);
}
public interface OnFindBookListener {
void onSuccess(String bookInfo);
}
}
可以看到Model不再持有Activity的引用,而是新增了一个回调方法,当获取到数据后,调用该回调方法,该回调方法在Presenter层中实现。下面我们看一下Presenter层:
package com.example.runningh.mydemo.testmvc;
/**
* Created by hwldzh on 2018/6/12
* 类描述: Presenter层
*/
public class PresenterBook {
private SearchBookActivity activity;
public PresenterBook(SearchBookActivity activity) {
this.activity = activity;
}
public void findBook() {
Book book = new Book(new Book.OnFindBookListener() {
@Override
public void onSuccess(String bookInfo) {
activity.updateView(bookInfo);
}
});
book.findBook();
}
}
Presenter层调用了Model层的findBook方法获取数据,并实现了获取数据后的回调方法,在回调方法中调用Activity的updateView方法通知Activity去刷新界面。Activity单独作为View层,和上面MVC的变化不大,我们看一下Activity作为的View层的代码逻辑:
package com.example.runningh.mydemo.testmvc;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.TextView;
import com.example.runningh.mydemo.R;
/**
* Created by hwldzh on 2018/6/12
* 类描述: View层
*/
public class SearchBookActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_book);
final PresenterBook presenterBook = new PresenterBook(this);
findViewById(R.id.find_books).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenterBook.findBook();
}
});
}
public void updateView(String bookInfo) {
TextView bookInfoView = findViewById(R.id.book_info_view);
bookInfoView.setText(getString(R.string.book_info, bookInfo));
}
}
3、优缺点
- 优点:
Model和View完全分离开,两者之间没有任何耦合,两者的修改互不影响。
Presenter可以作用于多个View,可以将公共的逻辑放在BasePresenter中,子类Presenter做一些和View相关的逻辑。
将逻辑放在Presenter中,可以脱离用户接口来测试这些逻辑(单元测试)。 - 缺点:
Presenter持有了Model和View的引用,其中包含了大量的控制逻辑,使得Presenter变得复杂而庞大,后期维护会比较困难。
4、适用场景
从MVP的优缺点可以得知每一个Presenter会和一个View对应起来,所以MVP适用于View不是很多的中型项目。
三、MVVM
1、MVVM简介
MVVM是Model View ViewModel的缩写。其中Model为模型,View为视图,ViewModel为View的数据模型和Presenter的合体,其实就是将MVP中的Presenter替换成了ViewModel,并通过双向数据绑定来实现View和ViewModel的交互。而在Android中一般使用Data Binding来实现双向的数据绑定。它的模式设计图如下所示:
MVVM开发设计图
它的工作流程和MVP模式差不多是一样的,只是将Presenter换成了ViewModel,并且将Presenter和View的交互方式用data-binding来进行代替。
在Android中,View对应着xml布局文件和Activity,Model对应着实体模型(网络、数据库、IO等),ViewModel作为View和Model两者之间的桥梁,除了兼具Presenter的功能外,它和View的交互使用了data-binding,使得View和ViewModel之间的耦合进一步降低。
2、MVVM的一个例子
要实现data-binding,我们需要在app下的gradle文件中进行如下配置:
android {
...
dataBinding {
enabled = true
}
...
}
继续使用上面那个例子,我们将MVP中的Presenter去掉,并写一个ViewModel对象,如下所示:
package com.example.runningh.mydemo.testmvc;
import android.databinding.BaseObservable;
import android.view.View;
/**
* Created by hwldzh on 2018/6/13
* 类描述: ViewModel层
*/
public class ViewModelBook extends BaseObservable {
public String bookInfo;
public View.OnClickListener btnListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
findBook();
}
};
public String getBookInfo() {
return bookInfo;
}
public void setBookInfo(String bookInfo) {
this.bookInfo = bookInfo;
notifyChange();
}
public View.OnClickListener getBtnListener() {
return btnListener;
}
public void setBtnListener(View.OnClickListener btnListener) {
this.btnListener = btnListener;
}
private void findBook() {
Book book = new Book(new Book.OnFindBookListener() {
@Override
public void onSuccess(String bookInfo) {
setBookInfo(bookInfo);
}
});
book.findBook();
}
}
可以看到ViewModel必须继承BaseObservable类,其中bookInfo是返回的图书信息,btnListener是点击按钮触发的事件。对于bookInfo和btnListener是要和View进行数据绑定的,所以在数据返回后,需要调用notifyChange方法。我们看一下View层的xml布局:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="searchBook"
type="com.example.runningh.mydemo.testmvc.ViewModelBook" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/find_books"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{searchBook.btnListener}"
android:text="寻找图书"/>
<TextView
android:id="@+id/book_info_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@{searchBook.bookInfo}"/>
</LinearLayout>
</layout>
再看View(Activity)的实现:
package com.example.runningh.mydemo.testmvc;
import android.app.Activity;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.example.runningh.mydemo.R;
import com.example.runningh.mydemo.databinding.SearchBooksBinding;
/**
* Created by hwldzh on 2018/6/12
* 类描述: View层
*/
public class SearchBookActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//SearchBookBinding类是由search_books布局自动生成
SearchBooksBinding binding = DataBindingUtil.setContentView(this, R.layout.search_books);
binding.setSearchBook(new ViewModelBook()); //setSearchBook方法是由search_books布局自动生成
}
}
3、优缺点
-
优点:
View和ViewModel之间的耦合度进一步降低,一个ViewModel可以绑定到不同的View上。
可重用性提高,可以将一些视图逻辑放在一个ViewModel中,让很多View重用这段视图逻辑。 -
缺点:
代码中的bug比较难发现,界面异常可能是View的问题,也可能是Model的问题,数据绑定使得该问题很难被发现。
数据双向绑定不利于代码重用。数据绑定让一个View和一个Model绑定起来,不同模块的Model基本上是不同的,这就是不能简单的重用View了。
4、适用场景
MVVM的开发模式适用于界面展示比较复杂,并且经常需要动态更新的项目。
网友评论