在开发应用程序的时候,以求更好的管理应用程序的复杂性,基于职责分离(Speration of Duties)的思想都会对应用程序进行分层.
软件工程熟悉的概念:高内聚,低耦合
耦合:
粗略地说,耦合就是两个东西通过某种作用连接在了一起。(我变你也变)
软件工程中耦合是指各个模块依赖程度,耦合越高,维护成本越高
为了便于维护,自然希望耦合越低越好。 ?
解耦:
解除耦合,弱化两个东西之间的联系,减少互相之间互相影响。(我变你不变)
耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合
尽量做到高内聚,低耦合
对于我们 Android 开发者来说,常见的架构模式基本上就是 MVC,MVP,MVVM,这三种也是开发 GUI 应用程序常见的模式。 除此之外还有 分层模式,客户端-服务器模式(CS模式),主从模式,管道过滤器模式,事件总线模式 等等。
应用程序的数据为Model,用户界面的层次称为View
MV*(MVC/MVP/MVVM)就是实现了领域模型数据和UI层的解耦。
MVC、MVP、MVVM对其解耦的思路的不同。从历史的角度来看,MVC、MVP和MVVM是一种进化的关系
MVC(Model-View-Centre)的依赖关系
?定义三个接口 (数据、视图、控制)
interface IModel {
/**
* 绑定 view
*/
fun setView(view:IView)
/**
* 数据模型 处理输入的数据
*/
fun dataHandler(data:String)
/**
* 数据模型 清除数据
*/
fun dataCleared()
}
interface IView {
fun setController(controller:IController)
/**
* 数据处理中状态
*/
fun dataHandlering()
/**
* 数据处理完成后 更新界面
*/
fun onDataHandled(data:String)
}
/**
* 控制器接口 定义控制器d逻辑
*/
interface IController {
fun setModel(model:IModel)
/**
* 数据变化后 通知控制器
*/
fun onDataChanged(data:String)
/**
* 清空按钮事件
*/
fun clearData()
}
?分别实现IModel和IController
class CModel : IModel {
private var view:IView? = null
private var handler: Handler = Handler(Looper.getMainLooper())
override fun setView(view: IView) {
this.view = view
}
override fun dataHandler(data: String) {
view?.dataHandlering()
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
if (TextUtils.isEmpty(data)){
view?.onDataHandled("")
}else {
view?.onDataHandled("look:${data}")
}
},2000)
}
override fun dataCleared() {
view?.onDataHandled("")
}
}
class CController : IController {
private var model:IModel? = null
override fun setModel(model: IModel) {
this.model = model
}
override fun onDataChanged(data: String) {
model?.dataHandler(data)
}
override fun clearData() {
model?.dataCleared()
}
}
IView在 对应Activity中实现
class MainMvcActivity : AppCompatActivity(),IView {
private var binding : ActivityMainBinding? = null
private var controller:IController = CController()//创建 控制器
private var model:IModel = CModel()//创建数据模型
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
controller.setModel(model)
this.setController(controller)//持有控制器
model.setView(this)//数据模型持有 view视图
binding?.editTextTextEmailAddress!!.addTextChangedListener(object : TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
controller.onDataChanged(s.toString())
}
override fun afterTextChanged(s: Editable?) {
}
})
binding?.clear!!.setOnClickListener {
controller.clearData()
}
}
override fun setController(controller: IController) {
// this.controller = controller
}
override fun dataHandlering() {
binding?.textView!!.text = "正在加载数据......"
}
override fun onDataHandled(data: String) {
if (TextUtils.isEmpty(data)){
binding?.editTextTextEmailAddress!!.setText("")
binding?.textView!!.text = "没有数据了"
}else{
binding?.textView!!.text = data
}
}
}
Ok完成!!!!
梳理一下:
请看IModel,IView,IController接口可以看到,View 持有 Controller,Controller持有 Model,Model 持有 View。这是MVC 的通信流程
再看?MainMvcActivity , binding?.clear 触发,通过 controller (controller.clearData()) 的clearData()方法,通知 Model(model?.dataHandler(data))执行?dataHandler(data)方法处理数据,处理完数据后 通过View (?onDataHandled(data:String)) 更新界面;
优点:
- 结构清晰,职责划分清晰
- 降低耦合
- 模块化程度高,有利于重用
缺点:
- 其实我们上述的示例,已经是经过优化的 MVC 结构了,一般来说,Activity / Fragment 会承担 View 和 Controller 两个角色,就会导致 Activity / Fragment 中代码较多
- Model 直接操作 View,View 的修改会导致 Controller 和 Model 都进行改动
- 增加了代码结构的复杂性
- Controller测试困难,视图同步操作是由View自己执行,而View只能在有UI的环境下运行。在没有UI环境下对Controller进行单元测试的时候,Controller业务逻辑的正确性是无法验证的:Controller更新Model的时候,无法对View的更新操作进行断言
MVP(Model View Presenter)
从MVC演化而来,控制逻辑,数据处理逻辑和界面交互耦合,同时能将 MVC 中的 View 和 Model 解耦控制逻辑,数据处理逻辑和界面交互耦合,同时能将 MVC 中的 View 和 Model 解耦
interface IModel {
fun setPersenter(p:IPersenter)
fun dataHeadler(data:String)
fun detaClear()
}
interface IView {
fun setPersenter(p:IPersenter)
fun loading()
fun showDate(data:String)
}
interface IPersenter {
fun setModel(m:IModel)//绑定 model
fun setView(v:IView)//绑定 view
fun dataChange(data:String)//model 数据处理完
fun dataCleared()//model 清除数据
fun onTextChanged(data: String)//view 数据变化
fun onBtnClicked()//view btn 清空数据
}
class PModel : IModel {
private var persenter:IPersenter? = null
private val handler : Handler = Handler(Looper.getMainLooper())
override fun setPersenter(p: IPersenter) {
this.persenter = p
}
override fun dataHeadler(data: String) {
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
if (TextUtils.isEmpty(data)){
persenter?.dataChange("")
}else{
persenter?.dataChange("MVP : ${data}")
}
},2000)
}
override fun detaClear() {
handler.removeCallbacksAndMessages(null)
persenter?.dataCleared()
}
}
class PPersenter : IPersenter {
private var model:IModel? = null
private var view:IView? = null
override fun setModel(m: IModel) {
this.model = m
}
override fun setView(v: IView) {
this.view = v
}
override fun dataChange(data: String) {
view?.showDate(data)
}
override fun dataCleared() {
view?.showDate("")
}
override fun onTextChanged(data: String) {
view?.loading()
model?.dataHeadler(data)
}
override fun onBtnClicked() {
model?.detaClear()
}
class MainMvpActivity : AppCompatActivity() , IView{
private var binding:ActivityMainBinding? = null
private var persenter:IPersenter? = null
private var pPersenter:IPersenter = PPersenter()
private var model:IModel = PModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
binding?.textView!!.text = "mvp"
this.setPersenter(pPersenter)
model.setPersenter(pPersenter)
pPersenter.setModel(model)
pPersenter.setView(this)
binding?.editTextTextEmailAddress!!.addTextChangedListener(object:TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
persenter?.onTextChanged(s.toString())
}
override fun afterTextChanged(s: Editable?) {
}
})
binding?.clear!!.setOnClickListener {
persenter?.onBtnClicked()
}
}
override fun setPersenter(p: IPersenter) {
this.persenter = p
}
override fun loading() {
binding?.textView!!.text = "MVP正在加载...."
}
override fun showDate(data: String) {
if (TextUtils.isEmpty(data)){
binding?.editTextTextEmailAddress!!.setText("")
binding?.textView!!.text = "没有数据!"
}else{
binding?.textView!!.text = data
}
}
操作流程:
view -- 》 persenter --》model --》persenter--》view
?Persenter 同时持有 Model和View,Model 和 View 单独持有Persenter。通过 Presenter 做中转
- 结构清晰,职责划分清晰
- 模块间充分解耦
缺点:
- 会引入大量的接口,导致项目文件数量激增
- 增大代码结构复杂性
更多了解:
Android官方MVP架构解读
官方MVP架构项目地址为:https://github.com/googlesamples/android-architecture. ?
|