MVP那些事儿(3)……在Android中使用MVC(上)架构
MVP那些事儿(4)……在Android中使用MVC(下)框架
立刻就要过春节了,如今还在单位刷掘金的同窗,可见大家在领导的心目中是何其重要,在这里,首先祝你们新春快乐、万事如意,新年新气象,来年再创新高!post
前面花了大量的篇幅去介绍分层架构的相关知识点,以及MVC架构是如何实现的,上一篇介绍了中介者模式与MVP间的关系,这期间应用了大量的场景描述,好比租房子的故事,项目开发的故事,加班的故事,这些铺垫都是为了能讲明白MVP,更是为了在之后的实战中能更加自由的去扩展和设计出新的变种,在项目中熟练应用,这就须要知其然,知其因此然。this
这一篇的能容比较单一,如何去设计一个MVP,由于有以前的铺垫,咱们直接用MVC的例子进行改写。spa
首先回顾一下MVC和MVP的区别,看下面这两张设计图,通过以前反复屡次的总结和概括,得出一个结论:
在MVC中,C的职责很是的单一,就是负责处理流程控制的,而在MVP中除了负责流程控制外,它还要负责M与V之间的一个隔离的做用,是做为一个中介者存在的。
什么是中介者? MVP那些事儿(5)中介者与MVP 欢迎回顾。
那么MVP的本质上就是中介者,从上面的结论中不难看出,只要让Controller赋予了中介者的职能,那么它就会变为Presenter。
隔离就意味着,在设计的过程当中,M和V之间是不能相互引用的,那么全部的交互都须要经过Controller去完成的,只要知足了这点,Controller就会升级为Presenter。咱们把以前的MVC调用方式的代码搬出来,从应用层倒推设计:
public class MainActivity extends AppCompatActivity implments TasksView{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化Controller,this就是View,经过构造器注入
TasksController controller = new TasksController(tasksView:this);
//初始化Model,Model -> View and View -> Model
TasksRepository model = new TasksRepository(tasksView:this);
//Controller -> Model
model.setController(controller);
}
}
复制代码
这一段代码是前几章中示例MVC中用到的,能够看到,在初始化TaskRepository时,经过构造函数将view注入到了TaskRepository,而这里的TaskRepository就是Model层的实例。咱们讲过,在MVP中,M与V不能以任何形式见面,可见上面的写法在MVP中是不容许的,因此须要从新设计,不容许View以各类形式出如今Moodel中,这其中就包括依赖注入的三种方式。其次,因为MainActivity是View的具体实现,很显然它实现了TaskView,虽然TaskView在设计中并无刻意的去包含Model,但却没法控制其子类包含有Model,这里TaskRepository在MainActivity中实例化了,它们一个表明着M,一个表明着V,可是在这里,其实并不会对总体设计带来影响,毕竟子类的行为是不受控制的,但为了规范使用,通常状况下Model的初始化是放在Presenter的实例中。在我看来这其实仍是有点好处,Presenter会去处理Model的初始化,这样,当View想使用不一样的Model时,直接去使用不一样Presenter便可。通过简单的分析,代码这样去修改
public class MainActivity extends AppCompatActivity implments TasksView{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化Controller,this就是View,经过构造器注入
TasksController controller = new TasksController(tasksView:this);
}
}
/** 因为TasksController中
public class TasksController implements Observer{
public TasksController(TasksView view) {
//经过构造函数接收view
this.view = view;
//经过构造函数初始化Model
TasksRepository model = new TasksRepository();
//Controller -> Model
model.addObserver(observer: this);
}
.
.
.
}
复制代码
经过以上的改造,Controller就变成了Presenter,别忘记修改类名,在真实的项目中,各个层大可能是以接口的形式定义的,这一点都不奇怪,没有接口哪里来的设计,因此别忘了作接口设计,在层的设计中,都是经过具体业务反推而来的,凭空想象是不可取的,若是有必定的积累和经验,能够先设计出来几个通用接口,而后再慢慢完善,好比Model加载数据的功能是比不可少的,那么能够先定义出loadData,比View接收到Presenter的通知,处理视图的方法,再好比Prensenter统一处理发起获取数据的请求等等。而这些具体业务的接口,才是MVP框架丰满的关键,但前提是咱们必定要去遵循MVP架构的原则去设计,那么接下来,咱们尝试这去设计这些接口。
框架即为骨骼,而接口和它的实现则是肌肉系统,接口决定了肌肉的走向,而实现则决定了肌肉的能力。
在最近的工做中,有这么一个需求,就是须要在App中同时存在http的请求和tcp的请求: 因为我不知道我获取的具体是什么东西,因此起名为getObject,同时我也不清楚具体参数和返回值(先忽略太多具体的业务)。
public interface DataSource {
void getObject();
}
复制代码
public interface Presenter {
void loadSometing();
}
复制代码
public interface View {
void setPresenter(Presenter p);
}
复制代码
public interface PresenterListener {
void onSametingCallBack()
}
复制代码
首先实现Model
public class RemoteHttpRepository implements DataSource {
@override
void getObject() {
//执行http请求
}
}
复制代码
public class RemoteTcpRepository implements DataSource {
@override
void getObject() {
//执行tcp请求
..
if(listener != null) {
listener.onSametingCallBack();
}
}
void addListener(PresenterListener listener) {
}
}
复制代码
实现View
public abstruct class BaseView implements View {
Presenter presenter;
void setPresenter(BasePresenter presenter) {
this.presenter = presenter
}
abstruct onViewDoSamething();
}
复制代码
实现 Presenter
public class BasePresenter implements Presenter ,PresenterListener{
RemoteTcpRepository repository;
View view;
public BasePresenter (View view) {
this.view = view;
//这里使用TCP请求
repository = new RemoteTcpRepository();
repository.addListener(presenterListener: this);
}
@Override
void loadSomething() {
repository.getObject();
}
@Override
void onSametingCallBack() {
view.onViewDoSamething();
}
}
复制代码
固然别忘了加入监听,上面的BasePresenter实现了监听,咱们在以前的章节介绍详细的介绍过监听的部分。
public class MainActivity extends AppCompatActivity implments BaseView{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Presenter presenter = new BasePresenter(view: this);
presenter.loadSamething();
}
@Override
void onViewDoSamething() {
//do view
}
}
复制代码
接口的定义要根据具体的业务去具体定义,上面的例子就是很是具体的业务去决定了接口的定义,因此,千万不要照葫芦画瓢,关键是要理解思想。
到此为止整个MVP的“肌肉”雏形就出来了,咱们继续向里面添加内容:好比,添加泛型对象、实现具体的网络请求功能、是否支持数据缓存、以及Presenter的生命周期控制,这些都须要你们根据实际需求去填充了,后天就是除夕了,立刻就要过节了,好开心,你们都好好多陪陪家人吧,工做什么的都去见鬼吧,哈哈哈,咱们节后再继续。