程序的本质

程序的本质在于模拟现实,但是有更明确的分工

简单的一个例子: 我 写 代码。

这是一个主谓结构: 主语->我,谓语->写,宾语->代码。

现在让我们来面向视角看问题:

  • 代码: 是个物体,是用来 被 写 的
  • 写: 是个动作,是用来 被 我执行的
  • 我: 是个物体,是用来 执行 写 这个动作 写代码的。

好,接着我们来面向对象写代码:

首先,创建一个我,这是个物体,所以应该创建一个对象:

public class Me {}

然后,需要有代码,才能写,代码也是一个物体,那么再创建一个对象:

public class Code {}

等等,代码应该有内容,有注释,好,我们来简单模拟下(程序就是模拟现实的):

public class Code {// 代码public String code;// 注释public String comment;
}

最后,需要创建一个写的动作,写既然是一个动作,不是物体,那么肯定是属于某个物体的行为,这里就是我的行为,动作就是函数(接口),于是就在 "我" 里面添加函数:

public class Me {// 添加写的行为,写什么?写代码public Code write() {Code code = new Code();code.code = "This is code";return code;}
}

这里有个问题,写过的代码,怎么展示出来呢,我们需要个显示器来显示,显示器是物体,所以我们需要定义个对象:

public class Display {// 显示器可以显示内容public void display(String content) {System.out.println(content);}
}

然后,我们需要展示我们的代码,我们可以直接这样改:

public class Me {// 添加写的行为,写什么?写代码public Code write() {// 写代码Code code = new Code();code.code = "This is code";// 展示Display display  = new Display();display.display(code.code);return code;}
}

这样当然没问题,但是,write()明明是一个写的函数,却额外做了展示的事情,不满足SRP,万一我只想写,不想展示呢,所以我们将函数分离职责,如下:

public class Me {// 添加写的行为,写什么?写代码public Code write() {// 写代码Code code = new Code();code.code = "This is code";return code;}// 展示代码public void showCode(){// 写代码Code code = write();// 展示Display display  = new Display();display.display(code.code);}
}

这样也不对,因为showCode()里面又调用了写的动作,showCode()应该只负责展示代码的,怎么办呢?追起根源,展示代码这个动作,并不是我自己的行为,所以不应该放在Me里面,任何人都可以展示代码,比如,我把自己的代码提供给第三方,第三方只要拿着显示器,就能展示出来,所以,展示代码这个事情,应该是属于第三方的,好,现在我们把Me里面的showCode()删掉,创建一个第三方场景类:

public class Client {// 展示代码public void showCode(){// 我来提供代码Me me = new Me();Code code = me.write();// 让显示器来展示Display display  = new Display();display.display(code.code);}
}

上面我们绕了一大圈,最后也就这么一句话: 我在Client中写了代码,然后把它展示了出来。用程序的话来说就是 Client控制我写出Code,然后控制Display展示Code

这里我们就引出了最基础的架构思想: MVC。MVC的核心就是一句话: C控制M展示在V上,这里Client就是C,Code就是M,Display就是V,所以是Client控制Code展示在Display上。至于Me,是负责提供生产Code的,就像是服务器是负责提供数据的一样。

MVC

MVC就是:Model,View,Controller的简写,核心是职责分离

我们知道,计算机由: 控制器,运算器,存储器,输入设备和输出设备组成,这里就是: 控制器 控制 存储器里面的内容 展示在 输出设备 上。所以MVC是个广义的思想,他不是架构,是思想,可以是物理的,也可以是虚拟的。

MVC的核心就是一句话: C控制M展示在V上,精粹就是四个字职责分离

这里再强调一下,MVC是广义的概念,广义的就是思想,不是架构,或者从狭义来说,它也是一种架构。

我们来看下MVC的结构图:

这里我们可以看到,MVC本身的耦合是挺严重的,M和V竟然也有关联,这确实不应该的。但是MVC的核心是职责分离而不是解耦合,体现在设计上就是,MVC的核心是单一职责,而不是最少知识

在普通的Android应用中,M就是数据,V就是xml布局,C明显就是Activity。这里有点不太对劲儿,Activity明明更像一个View,因为它有findViewById()的方法,为什么又是C呢,这岂不是违背了MVC的职责分离明确的原则吗?这只能说谷歌设计的不太好。于是就有了下面的MVP模式。

MVP

MVP就是:Model,View,Presenter,这里把Controller替换为了Presenter。

MVP的核心除了MVC的职责分离,还有解耦合,也就是说,他在满足单一职责的基础上,又满足了最少知识原则。我们看下它的结构图:

这里我们看到,View和Model没有关联了,它们都通过Presenter来沟通,是不是有点像中介者模式。中介者模式的优点不就是解耦合吗,正好!

现在假如我们使用了MVP模式,我们的代码看起来是这样:

class Model {Presenter presenter;
}class View {Presenter presenter;
}class Presenter {Model model;View view;
}

可以看到,View和Model是零耦合的。

那么事件的流向就是: View -> Presenter -> Model

数据的流向就是: Model -> Presenter -> View

中间都需要经过Presenter。

当我们在Android中使用时,可以把Activity当作Presenter,把xml当作View,当然也可以直接把Activity抽空,自定义一个Presenter。这里我们来个简单的例子示例一下MVP中事件和数据的流向。

假设现在屏幕上有一个按钮,点击之后需要展示数据,事件肯定是屏幕引起的,也就是View,所以事件的出发点是View。

public class View {Presenter presenter;// 1 发出事件public void click(){presenter.getInfo();}// 6 接收并展示数据public void showInfo(String info){setInto(info);}
}public class Presenter {Model model;View view;// 2 传递事件public void getInfo(){model.getInfo();}// 5 传递数据public void onGetInfo(String info){view.showInfo(info);}
}public class Model {Presenter presenter;// 3 接收并处理事件public void getInfo(){String info = getInfoFromServer();// 4 发出数据presenter.onGetInfo(info);}// 模拟从服务器获取数据private String getInfoFromServer(){String info =  "this is info";return info;}
}

事件的流向(1->2->3): View.click() -> presenter.getInfo() -> model.getInfo() -> 从服务器获取数据。

数据的流向(4->5->6): model.getInfo() -> presenter.onGetInfo(info) -> view.showInfo(info) -> 展示在屏幕上。

可以看到,View是事件的发起者和数据的接收者,Model是事件的接收者和数据的发起者,Presenter只是起个中转作用

好,现在我们知道了MVP除了具有MVC的职责分离优点,还能解耦合。接下来我们来看自动化的MVP-MVVM

MVVM

MVVM就是: Model,View,ViewModel。

MVVM的核心是观察者模式,MVVM已经不再职责分离了,当然也没解耦合,他的特点就是响应式。什么意思呢,就是说: 我这边数据变了,你那边立刻知道,不需要经过谁来通知。

官方的图是这样的,View和Modle无关联,但是这是不严谨的,因为对于MVVM来说,Model数据变了后,需要通知到View,那么肯定需要直接或间接持有View的引用,所以这个图是不严谨的。

我们将上述MVP的代码改写为MVVM。

class View {ViewModel vm;// 订阅Model的数据private void init(){vm.getModel.observer(content, new Observer() {public void onInfo(String info) {// 6 接收到数据并展示showInfo(info);}})}// 1 发起事件private void click(){vm.getInfo();}// 7 展示数据private void showInfo(String info){setInfo(info);}
}class ViewModel {Model model;Model getModel(){return model;}// 2 传递事件public void getInfo(){model.getIndo();}
}class Model {// 定义观察者,这里已经持有观察者了,也就是持有View了。List<Observer> observers;// 添加观察者public void observe(Observer observe){observers.add(observe);}// 3 接收并处理事件public void getInfo(){// 4 获取数据String info = getInfo();// 5 通知数据改动for(Observer observer : observers) {observer.onInfo(info);}}// 模拟从服务器获取数据private String getInfoFromServer(){String info =  "this is info";return info;}
}

经过上面伪代码,我们发现ViewModel只传递了事件,不再传递数据了,数据是直接由Model通知到View的,所以我们的:

事件流向: View.click() -> ViewModel.getInfo() -> Model.getInfo() -> 获取数据。

数据流向: Model.getInfo() -> View.Observer.onInfo(info) -> View.showInfo() -> 展示数据。

这里有个很egg pain的点,就是Model间接持有View,第一就是会导致耦合,第二就是可能发生内存泄漏,我们知道Model的生命周期是大于View的,所以要在View消失的时候去反注册掉。当然,使用LiveData可以更好的解决问题。

那么,MVVM的优点在哪呢?就是你不用去主动去刷新UI了,只要Model数据变了,会自动反映到UI上。换句话说,MVVM更像是自动化的MVP

总结

  • MVC更像是一种思想,它描述一种职责分离的思想
  • MVP是MVC的一种表现,它出了具备职责分离,还具备解耦合
  • MVVM是自动化的MVVM,它具备职责分离,具备松耦合,同时还能自动响应数据。

如果你的业务是少量的重逻辑,建议使用MVP(debug方便);如果你的业务是大量的轻逻辑,最好使用MVVM(自动响应数据方便)。

站在思想层面看MVX架构相关推荐

  1. 第十二课 从宠物商店案例看DAPP架构和WEB3.JS交互接口

    1. 文章摘要 [本文目标] 了解ETH生态下DAPP去中心化应用程序的框架和交互流程,了解WEB3.JS的作用和接口函数. [前置条件] 完成了<第六课 技术小白如何开发一个DAPP区块链应用 ...

  2. 从淘宝来看后端架构发展

    本文以淘宝的发展来说明后端架构的发展 文章目录 概述 基本概念 架构演进 架构设计总结 本文小结 概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进 ...

  3. 面向对象思想----不看懊悔!

    面向对象思想----不看懊悔! 前言: 整理这份资料的目的是为了帮助朋友们可以更直观的理解面向对象的编程.让后来者可以少走一些弯路.但当中不免有很多漏洞及错误,也还 请前辈提出宝贵的更改意见,毕竟交流 ...

  4. 从技术细节看美团架构

    转载:http://www.infoq.com/cn/articles/see-meituan-architecture-from-technical-details 编者按:本文是根据ArchSum ...

  5. 十位数据库专家:如何透过性能优化看系统架构的合理性

    十位数据库专家:如何透过性能优化看系统架构的合理性 本文首发于一年多以前,由当时十位民生银行的数据库专家合著,系统地从架构的角度对数据库性能问题进行分析解读b,是多年项目开发和运维工作的经验总结.文章 ...

  6. 使用网站模板快速建站_建站工具使用教程看了就懂网站建设

    做网站敲代码早已是过去式,使用建站工具制作网站以是主流,初次接触建站工具难免对它有所不了解,广州半岛网络科技有限公司就以"云建站"为使用案例,把操作建站过程梳理写成教程,方便大家看 ...

  7. 大多数项目能不能投资,能不能去创业,取决于自己是站在什么高度看问题

    大多数项目能不能投资,能不能去创业,取决于自己是站在什么高度看问题. 同一个项目,老板觉得有把握,员工觉得没把握,不是因为老板有钱输得起,员工输不起,因为好项目老板也是需要负债去做的,但对很多员工来说 ...

  8. 你站在桥上看风景,看风景的人在楼上看你

    当你的才华还撑不起你的野心的时候,你就应该静下心来学习:当你的能力还驾驭不了你的目标时,就应该沉下心来,历练:梦想,不是浮躁,而是沉淀和积累,只有拼出来的美丽,没有等出来的辉煌,机会永远是留给最渴望的 ...

  9. android手机b站看直播,b站直播怎么回看 b站手机直播查看回放教程

    b站直播怎么回看?b站直播能看回放吗?如果你错过了某位主播的直播,想要看回放的话,可以来看看本文提供的b站直播回放教程. b站直播怎么回看? b站直播主要是让您进行直播与其他的小伙伴互动使用的的,目前 ...

  10. 巴比特 | 元宇宙每日必读:数字藏品还能怎么玩?以B站为例,看当前玩家们的现状...

    摘要:B站近期上新动作频频,尤其是7月,总共发行了8套数字藏品.据新榜编辑部统计,截至8月10日,B站共推出17个系列数字藏品,其中除了官方原创IP,还包括游戏.电影.文博.虚拟主播.UP主等联合定制 ...

最新文章

  1. 通过一个案例理解 JWT
  2. android opengl es 粒子效果实例代码
  3. 将对话框(提示框)中的内容粘贴到记事本
  4. pb通过对象名称调用对象_信号线名称自动关联Simulink信号对象
  5. 小米MIX4曝光,颜值真不错
  6. Hbuilder开发HTML5 APP之图标和启动页制作
  7. 归并有效排序算法matlab,科学网—[用MATLAB写算法]之排序算法2)归并排序merge sort - 徐勇刚的博文...
  8. 微信公众号推送(Java)
  9. 《因果推理原理:基础与学习算法》第一章 因果模型和统计模型
  10. AutoCAD2007 快捷键介绍和线形设置
  11. python自动打印如何实现-Python 实现自动完成A4标签排版打印功能
  12. java 判断是否闰年_输出月份天数_Java判断闰年平年并输出某月的天数
  13. 数字电路设计之低功耗设计方法六:旁路(by-passing)
  14. Java 利用ffmpeg工具实现视频MP4转m3u8
  15. 亚马逊Amazon-API接口使用说明
  16. Lambda 表达式(一)-码住
  17. 工业螺旋齿轮行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  18. [附源码]Python计算机毕业设计SSM旅行组团服务管理系统(程序+LW)
  19. 渗透测试工具:跨站脚本漏洞检测---Xsser
  20. [杂谈]微软亚洲研究院院长洪小文博士写给你的新年书单

热门文章

  1. python更改pip源地址
  2. latex调整caption字体大小
  3. uniapp 集成腾讯云超级播放器问题
  4. 使用聚合数据接口发送短信
  5. 学习shell推荐书籍清单
  6. 台式机装苹果系统_AMD台式机装苹果系统!!
  7. TCP/IP 系列之你真的知道什么叫做IP吗?
  8. layui模板引擎文档 - layui.laytpl的具体使用
  9. 缩写月份单词python_月份的英文单词、缩写及由来
  10. router 路由守卫