Mvc、Mvp和Mvvm

一.概念

1.框架模式和设计模式

  • 简单理解,框架面向一系列相同行为代码的重用,而设计模式面对的是一系列相同结构代码的重用;
  • 软件开发领域三种级别的重用
    • 内部重用,在同一应用中能公共使用的抽象块;
    • 代码重用,通用模块组合成库或工具类,及在多个应用和领域中都能重用;
    • 应用框架的重用,专用领域提供通用的或现成的基础结构,以获得最高级别的重用性;

二.Mvc

1.全称:Model–View–Controller

  • 模型(Model)-视图(View)-控制器(Controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界
    面显示分离的方法组织代码;
  • 视图层(View)
    • 对应于Xml布局文件和Java代码动态View部分;
  • 控制层(Controller)
    • MVC中Android的控制层是由Activity来承担的;
    • Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多;
  • 模型层(Model)
    • 针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作;
  • 通信方式(所有通信都是单向的)
    • View 传送指令到 Controller;
    • Controller 完成业务逻辑后,要求 Model 改变状态;
    • Model 将新的数据发送到 View,用户得到反馈;

2.mvc在android中的代码实现

2.1.BaseModel,所有业务逻辑model的父类

public interface BaseModel {
    //用于跟activity或者fragment生命周期同步,在destroy做一些销毁操作
    void onDestroy();
}

2.2.Callback:根据View或者Controller调用Model时回调的参数个数选择使用

public interface Callback1<T> {
    void onCallBack(T t);
}
public interface Callback2<T,P> {
    void onCallBack(T t,P p);
}

2.3.具体的SampleModel

public class SampleModel  implements BaseModel{

    public void  getUserInfo(String uid,Callback1<UserInfo> callback)
    {

        UserInfo userInfo= new HttpUtil<UserInfo>().get(uid);
        callback.onCallBack(userInfo);

    }

    @Override
    public void onDestroy() {

    }

    public class UserInfo
    {
        private int age;
        private String name;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

2.4.SampleActivity:充当View和Controller

public class SampleActivity extends AppCompatActivity {
    private SampleModel sampleModel;
    Button button;
    EditText textView;
    TextView tvAge,tvName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);
        sampleModel=new SampleModel();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getUserInfo(textView.getText().toString());
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sampleModel.onDestroy();
    }

    /**
     * 获取用户信息
     * @param uid
     */
    private void getUserInfo(String uid)
    {
        sampleModel.getUserInfo(uid, new Callback1<SampleModel.UserInfo>() {
            @Override
            public void onCallBack(SampleModel.UserInfo userInfo) {
                setDataToView(userInfo);
            }
        });
    }

    /**
     * 设置用户信息到view
     */
    private void setDataToView(SampleModel.UserInfo userInfo)
    {
        tvAge.setText(userInfo.getAge());
        tvName.setText(userInfo.getName());
    }

}

3.Mvc总结

  • 3.1.控制器Activity
    • 主要起到的作用就是解耦,将视图View和Model进行分离;
    • View和Model在Activity中进行绑定或完成其它逻辑;
  • 3.2.优点
    视图View和Model进行分离,降低耦合度;
  • 3.3.缺点
    • Activity类过于臃肿;
    • View 无法组件化。View 是强依赖特定的 Model 的,如果需要把View 抽出来作为一个另外一个应用程序可复用的组件就困难了;

二.Mvp

1.特点

  • MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向;
  • 各部分之间的通信,都是双向的;
  • View 与 Model 不发生联系,都通过 Presenter 传递;
  • View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里;

2.Mvp代码示例

2.1.BasePresenter:类似于MVC中的BaseModel

public interface BasePresenter {
    void onDestroy();
}

2.2.BaseView:是所有View的父类

  • 将android中的view抽象化出来,只有跟view相关的操作都由baseView的实现类去完成。
public interface BaseView<P extends BasePresenter> {
    void setPresenter(P presenter);
}

2.3.Contract 契约类

  • 用于定义同一个界面的view的接口和presenter的具体实现。
  • 好处是通过规范的方法命名和注释可以清晰的看到整个页面的逻辑。
public class SampleContract {
    public static class Presenter implements BasePresenter
    {
        public void  getUserInfo(String uid,Callback1<SampleModel.UserInfo> callback)
        {
            SampleModel.UserInfo userInfo= new HttpUtil<SampleModel.UserInfo>().get(uid);
            callback.onCallBack(userInfo);
        }

        @Override
        public void onDestroy() {

        }
    }
    public interface View extends BaseView<Presenter>
    {
         void setDataToView(SampleModel.UserInfo userInfo);
    }
}

2.4.SampleActivity

  • SampleActivity实现了SampleContract.View只是作为View存在的
public class SampleActivity extends AppCompatActivity implements SampleContract.View{
    private  SampleContract.Presenter mPresenter;
    Button button;
    EditText textView;
    TextView tvAge,tvName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);
        setPresenter(new SampleContract.Presenter());

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPresenter.getUserInfo(textView.getText().toString(), new Callback1<SampleModel.UserInfo>() {
                    @Override
                    public void onCallBack(SampleModel.UserInfo userInfo) {
                        setDataToView(userInfo);
                    }
                });
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.onDestroy();
    }

    @Override
    public void setDataToView(SampleModel.UserInfo userInfo) {
        tvAge.setText(userInfo.getAge());
        tvName.setText(userInfo.getName());
    }


    @Override
    public void setPresenter(SampleContract.Presenter presenter) {
        mPresenter=presenter;
    }
}

3.Mvp总结

  • 通过引入接口BaseView,让相应的视图组件如Activity,Fragment去实现BaseView,实现了视图层的独立;
  • 通过中间层Preseter实现了Model和View的完全解耦;
  • 优点
    • mvp解决了mvc的Controller和View很难做到完全解耦的问题;
    • View 可以进行组件化。在 MVP 当中,View 不依赖 Model。这样就可以让 View 从特定的业务场景中脱
      离出来,可以说 View 可以做到对业务逻辑完全无知。它只需要提供一系列接口提供给上层操作。这样就可
      以做高度可复用的 View 组件;
  • 缺点
    随着业务逻辑的增加,一个页面可能会非常复杂,UI的改变是非常多,会有非常多的case,这样就会造成View的接口会很庞大。

三.Mvvm

  • MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致;
  • 唯一的区别是,它采用双向绑定(Mvvm的核心data-binding):View的变动,自动反映在 ViewModel,反之亦然;
  • mvp中随着业务逻辑的增加,UI的改变多的情况下,会有非常多的跟UI相关的case,这样就会造成View的接口会很庞大。 mvvm解决了mvp的这个问题,通过双向绑定的机制,实现数据和UI内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了很多在View层中写很多case的情况,只需要改变数据就行;
  • Activity和xml layout充当View,ViewModel处理业务逻辑以及获取数据,弱化Model;

1.代码示例

1.1.BaseViewModel

  • ViewMode层主要处理业务逻辑和获取数据,mViewDataBinding是通过View层传递过来。
public interface BaseViewModel {
    void onDestroy();
}

public abstract class AbstractViewModel<T extends ViewDataBinding> implements BaseViewModel {
    public T mViewDataBinding;
    public AbstractViewModel(T viewDataBinding)
    {
        this.mViewDataBinding=viewDataBinding;
    }

    @Override
    public void onDestroy() {
        mViewDataBinding.unbind();
    }
}

public class SampleViewModel extends AbstractViewModel<ActivitySampleMvvmBinding> {

    public SampleViewModel(ActivitySampleMvvmBinding viewDataBinding) {
        super(viewDataBinding);
    }

    public  void getUserInfo(String uid, Callback1<SampleModel.UserInfo> callback)
    {
        //从网络或缓存获取信息
        SampleModel.UserInfo userInfo=new SampleModel.UserInfo();
        userInfo.setName("tom");
        userInfo.setAge(18);
        callback.onCallBack(userInfo);
    }
}

2.Mvvm总结

  • 解决MVP中View层好多接口的问题,让View变得更简洁;
  • View的变动,自动反映在 ViewModel,反之亦然;
  • 看起来MVVM很好的解决了MVC和MVP的不足,但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能数据问题导致,也有可能业务逻辑中对视图属性的修改导致。如果项目中打算用MVVM的话可以考虑使用官方的架构组件ViewModel、LiveData、DataBinding去实现MVVM(项目中已经使用,至今有一年多,待,待改善、整理到开源项目中);
  • 优点
    • 提高可维护性。解决了 MVP 大量的手动 View 和 Model同步的问题,提供双向绑定机制。提高了代码的可维护性;
    • 简化测试。mvp中View与Model的同步是交给Presenter去做的,在mvvm中,不需要手动去完成,交由databinding实现。Model变化,View会跟着Model同时变更,所以只需要保证Model的正确性,View就正确。大大减少了对 View 同步更新的测试;
  • 缺点
    • 过于简单的图形界面不适用,或说牛刀杀鸡;
    • 对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高;
    • 数据绑定的声明是指令式地写在 View 的模版当中的,这些内容是没办法去打断点 debug 的;

四.Mvc/Mvp/Mvvm比较

  • Mvp不是一个标准化的模式,它有很多种实现方式,可以根据自己的需求或者认为对的方式去修正Mvp的实现方式,可以随Presenter的复杂程度变化。只要保证是通过Presenter将View和Model解耦;
  • 通过以上可以看出,Mvc的耦合度还是相对较高,View可以直接访问Model,导致三者之间形成回路;
  • Mvc与Mvp的主要区别:Mvp的View不能直接访问Model,需要通过Presenter发出请求,View与Model不直接通信;
  • Mvp和Mvvm的结构非常相似,唯一的区别是View和Model进行双向绑定,两者有一方变化会反应到另一方上。而Mvp和Mvvm的主要区别是Mvp的View更新需要通过Presenter,而Mvvm不需要;

五.总结

  • 项目如果简单,维护性不高,将模块封装好,不需要采用什么架构和设计模式,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用;
  • 小型项目可以采用Mvc;
  • 侧重于数据展示和交互(对于偏向展示型的App,绝大多数业务逻辑都在后端,App主要功能就是展示数据,交互等),建议采用Mvvm;
  • 大型项目,业务复杂的采用Mvp;
  • 对于工具类或者需要写很多业务逻辑App,Mvp或者Mvvm都可,可根据具体的项目灵活的对架构进行选择(如:混合架构)等;

六.参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值