瞭解如何分析一個架構模式
掌握 MVC,MVP,MVVM 架構定義和實現
更多面試內容,面試專題,flutter視頻 全套,音視頻從0到高手開發。
關注GitHub:https://github.com/xiangjiana/Android-MS
免費獲取面試PDF合集
免費提供簡歷修改建議,獲取大廠面試PDF和視頻教程android
關於架構的定義,其實在不少書籍和文章中都是不一樣的,很難作一個統一。這裏列舉兩個定義: git
在維基百科裏是這樣定義的:程序員
軟件架構是一個系統的草圖。軟件架構描述的對象是直接構成系統的抽象組件。各個組件之間的鏈接則明確和相對細緻地描述組件之間的通信。在實現階段,這些抽象組件被細化爲實際的組件,好比具體某個類或者對象。 github
在 IEEE 軟件工程標準詞彙中是這樣定義的: 面試
架構是以組件、組件之間的關係、組件與環境之間的關係爲內容的某一系統的基本組織結構,以及指導上述內容設計與演化的原理。設計模式
在看過茫茫多的架構定義之後,我理解的架構是這樣的:服務器
1.爲了解決特定的問題而提出
2.按照特定的原則將系統總體進行模塊/組件/角色的劃分
3.創建模塊/組件/角色間的溝通機制
具體解釋一下,首先是要有特定的問題,沒有問題空談架構,彷彿是空中樓閣,沒有實用價值,而對應到不一樣的問題,會有不一樣的解決方式。
其次是模塊的劃分要根據特定的原則,沒有原則隨意劃分,也就無從去評估一個架構的好壞。最後就是模塊間的通訊機制,讓系統成爲一個總體.網絡
最後,架構模式,其實更多的是一種思想,一種規則,每每一種架構模式可能會有不一樣的實現方式,而實現方式之間,只有合適與否,並無對錯之分。數據結構
上面咱們介紹了架構的定義,根據這個定義,咱們在後面分析架構模式的時候,也會從這三方面進行。架構
知道了架構模式要解決的問題,咱們才能針對性的去看,去想其解決方法是否得當,是否合適。
架構中最重要的就是角色 / 模塊的劃分,理解了架構模式中的角色劃分,才能更好的理解其結構。
角色間的通訊也是重要的。相同的角色劃分,採用不一樣的通訊方式,每每就構成了不一樣的架構模式。
角色間通訊咱們能夠理解爲數據的流向。在 Android 開發中,通訊中的數據能夠理解爲兩種,一種是數據結構,也就是網絡請求,本地存儲等通訊使用的 JavaBean,另外一種是事件,也就是控件產生的動做,包括觸摸,點擊,滑動等等。咱們在通訊過程當中,也主要關注這兩種數據。
對於咱們 Android 開發者來講,常見的架構模式基本上就是 MVC,MVP,MVVM,這三種也是開發 GUI 應用程序常見的模式。
除此以外還有 分層模式,客戶端-服務器模式(CS模式),主從模式,管道過濾器模式,事件總線模式 等等。
這篇文章仍是具體分析 MVC,MVP,MVVM 這三種架構模式。
咱們在瞭解架構的定義之後,可能會想,爲何要用這些架構模式呢?在咱們不瞭解這些模式以前,也是同樣的開發。相似設計模式,其實架構模式的目的不是爲了讓應用軟件開發出來,而是讓結構更清晰,分工更明確,擴展更方便等等。
咱們能夠看看,在不使用架構模式以前咱們是怎麼開發的。
舉個簡單的栗子,咱們界面上有 EditText
,TextView
,Button
三個控件,要實現的功能也比較簡單:
1.EditText
接受用戶輸入的內容
2.處理用戶輸入的數據
3.數據處理後輸出到TextView
中
4.點擊Button
清空用戶的輸入
界面以下:
咱們看看不使用架構模式是怎麼開發的,也就是咱們通常經常使用的開發方式:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" tools:context=".MainActivity"> <TextView android:id="@+id/titleText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Normal" /> <EditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="50dp" android:textColor="@android:color/darker_gray" /> <TextView android:id="@+id/msgText" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_marginTop="10dp" android:text="default msg" android:textColor="@android:color/darker_gray" /> <TextView android:id="@+id/clearText" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:gravity="center" android:text="clear" android:textColor="@android:color/white" /> </LinearLayout>
1.在 Activity / Fragment
中獲取 View
,進行事件監聽
2.經過 View
事件獲取數據後進行處理
3.設置處理後的數據給 View
代碼以下:
class NormalFragment : Fragment() { companion object { fun newInstance(): Fragment { return NormalFragment() } } private val handler: Handler = Handler() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.architecture, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) titleText.text = "NORMAL" edit.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { handleData(s.toString()) } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } }) clearText.setOnClickListener { edit.setText("") } } // 數據的處理,真實狀況下多是網絡請求,磁盤存取,大量計算邏輯等等 private fun handleData(data: String) { if (TextUtils.isEmpty(data)) { msgText.text = "default msg" return } msgText.text = "handle data ..." handler.removeCallbacksAndMessages(null) // 延遲來模擬網絡或者磁盤操做 handler.postDelayed({ msgText.text = "handled data: $data" }, 3000) } }
默認開發方式的缺點:
咱們來分析一下上面的代碼,一個明顯的特色就是處理邏輯都集中在了 Activity / Fragment
中,無論是對 View
的操做,仍是對數據的處理。帶來的問題就是 Activity / Fragment
中邏輯臃腫,後續擴展牽一髮而動全身。並且職責劃分不清晰,給後續維護也帶來了困難。
既然如此,咱們看看使用架構模式改造後是什麼樣子的。
其實關於 MVC
架構,在不一樣的框架裏,實現會有些差異,這也正說明了架構是一種思想。咱們這裏選用一種比較主流的實現。
咱們能夠看到,上面不使用架構進行開發,帶來的問題是 Activity / Fragment 邏輯臃腫,不利於擴展。因此 MVC 就要解決的問題就是:控制邏輯,數據處理邏輯和界面交互耦合。
這裏先插一個題外話,其實咱們做爲程序員,寫代碼不只要實現需求,還要讓代碼易讀,易擴展。這一點,每每也能體現功力,並非說使用了各類奇技淫巧纔是大神。
不知道你們是否有接觸過 Java Swing 桌面應用開發,在 Java Swing 中,界面 / 控件的設置,也是用 Java 代碼來實現的,若是不採用架構,最後的結果就是控制邏輯,數據處理以及頁面展現的代碼都集中在一個類中,讀者朋友們能夠想象一下,這樣的代碼簡直是難以維護
爲了解決上面的問題,MVC
架構裏,將邏輯,數據,界面的處理劃分爲三個部分,模型(Model)-視圖(View)-控制器(Controller)。各個部分的功能以下:
Model
模型,負責數據的加載和存儲。View
視圖,負責界面的展現。Controller
控制器,負責邏輯控制。咱們再看看三者之間是怎麼通訊的。
在介紹通訊以前,咱們先解釋一下通訊中的數據是什麼。其實在 Android 開發中,通訊數據能夠理解爲兩種,一種是數據結構,也就是網絡請求,本地存儲等通訊使用的 JavaBean
,另外一種是事件,也就是控件產生的動做,包括觸摸,點擊,滑動等等。咱們在通訊過程當中,也主要關注這兩種數據。
在 MVC
架構中,View
產生事件,通知到 Controller
,Controller
中進行一系列邏輯處理,以後通知給 Model
去更新數據,Model
更新數據後,再將數據結構通知給 View 去更新界面。
這就是一個完整 MVC
的數據流向
理解了 MVC
模式,咱們看看其具體實現。
其實在 Android 開發中,其自己默承認以理解爲 MVC
結構,把 View
放在 xml
中與 Java
代碼解耦,而後 Activity / Fragment
充當 Controller
進行邏輯控制,可是 Android 自己並無對 Model
進行劃分,因此每每咱們會讓 Activity / Fragment
充當 Model
和 Controller
兩個角色。並且每每 xml
中的 View
操做也是在 Activity / Fragment
中,致使有時候 Activity / Fragment
也會充當一些 View
的角色。
因此咱們在具體實現過程當中,要把職責劃分清楚,這裏咱們讓 Fragment
充當 View
的角色,把 Model
和 Controller
的邏輯劃分清楚。
咱們先定義三個接口以下:
// 數據模型接口,定義了數據模型的操做 interface IModel { fun setView(view: IView) // 數據模型處理輸入的數據 fun handleData(data: String) // 清空數據 fun clearData() } // 視圖接口,定義視圖的操做 interface IView { fun setController(controller: IController) // 數據處理中狀態 fun dataHanding() // 數據處理完成,更新界面 fun onDataHandled(data: String) } // 控制器接口,定義控制器的邏輯 interface IController { fun setModel(model: IModel) // EditText 數據變化,通知控制器 fun onDataChanged(data: String) // 清空按鈕點擊事件 fun clearData() }
上面三個接口分別定義了 Model,View,Controller
的操做。有一點注意的是,根據 MVC
的通訊流程,View
須要持有 Controller
,Controller
須要持有 Model
,Model
須要持有 View
,因此須要暴露相應的接口。
下面咱們看看具體的實現:
Model 中對數據的處理是添加了 "handled data: "
前綴,並增長了 3 秒的延遲
class HandleModel : IModel { private var view: IView? = null private val handler: Handler = Handler(Looper.getMainLooper()) override fun setView(view: IView) { this.view = view } // 接受到數據後,進行處理,這裏設置了 3 秒的延遲,模擬網絡請求處理數據的操做 override fun handleData(data: String) { if (TextUtils.isEmpty(data)) { return } view?.dataHanding() handler.removeCallbacksAndMessages(null) // 延遲來模擬網絡或者磁盤操做 handler.postDelayed({ // 數據處理完成,通知 View 更新界面 view?.onDataHandled("handled data: $data") }, 3000) } // 接收到清空數據的事件,直接清空數據 override fun clearData() { handler.removeCallbacksAndMessages(null) // 數據清空後,通知 View 更新界面 view?.onDataHandled("") } }
Controller
的實現比較簡單,將操做直接轉發給 Model
,實際上,對於複雜的業務場景,這裏要處理不少業務邏輯。
class HandleController : IController { private var model: IModel? = null override fun onDataChanged(data: String) { model?.handleData(data) } override fun clearData() { model?.clearData() } override fun setModel(model: IModel) { } }
這裏 Fragment
充當了 View
的角色,主要負責將 View
的事件傳遞給 Controller
,以及接受到 Model
的數據進行界面更新。
class MVCFragment : Fragment(), IView { companion object { fun newInstance(): Fragment { return MVCFragment() } } private val model: IModel = HandleModel() private var controller: IController = HandleController() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.architecture, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setController(controller) model.setView(this) titleText.text = "MVC" edit.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { // 通知 Controller 輸入的數據產生變化 controller?.onDataChanged(s.toString()) } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } }) clearText.setOnClickListener { // 通知 Controller 清空數據事件 controller?.clearData() } } // Model 數據變化,進行界面更新 override fun onDataHandled(data: String) { if (TextUtils.isEmpty(data)) { edit.setText("") msgText.text = "default msg" } else { msgText.text = data } } // Model 數據變化,進行界面更新 override fun dataHanding() { msgText.text = "handle data ..." } override fun setController(controller: IController) { this.controller = controller } }
這樣咱們就實現了一個簡單的 MVC
結構。
MVC
結構了,通常來講,Activity / Fragment
會承擔 View
和 Controller
兩個角色,就會致使 Activity / Fragment
中代碼較多View
,View
的修改會致使 Controller
和 Model
都進行改動MVP 要解決的問題和 MVC
大同小異:控制邏輯,數據處理邏輯和界面交互耦合,同時能將 MVC
中的 View
和 Model
解耦。
MVP 架構裏,將邏輯,數據,界面的處理劃分爲三個部分,模型(Model)-視圖(View)-控制器(Presenter)。各個部分的功能以下:
Model
模型,負責數據的加載和存儲。View
視圖,負責界面的展現。Presenter
控制器,負責邏輯控制咱們能夠看到,MVP 中的各個角色劃分,和 MVC
基本上類似,那麼區別在哪裏呢?區別就在角色的通訊上。
MVP
和 MVC
最大的不一樣,就是 View
和 Model
不相互持有,都經過 Presenter
作中轉。View
產生事件,通知給 Presenter
,Presenter
中進行邏輯處理後,通知 Model
更新數據,Model
更新數據後,通知數據結構給 Presenter
,Presenter
再通知 View
更新界面。
這就是一個完整 MVP 的數據流向。
理解了 MVP
以後,咱們看一下其具體實現。
首先咱們定義三個接口:
// 模型接口,定義了數據模型的操做 interface IModel { fun setPresenter(presenter: IPresenter) // 梳理數據 fun handleData(data: String) // 清除數據 fun clearData() } // 視圖接口,定義了視圖的操做 interface IView { fun setPresenter(presenter: IPresenter) // 數據處理中視圖 fun loading() // 數據展現 fun showData(data: String) } // 控制器,定義了邏輯操做 interface IPresenter { fun setView(view: IView) fun setModel(model: IModel) // Model 處理完成數據通知 Presenter fun dataHandled(data: String) // Model 清除數據後通知 Presenter fun dataCleared() // View 中 EditText 文字變化後通知 Presenter fun onTextChanged(text: String) // View 中 Button 點擊事件通知 Presenter fun onClearBtnClicked() }
上面定義了 View,Model,Presenter
三個接口,其中 View
和 Model
會持有 Presenter
,Presenter
持有 View
和 Model
。
接着看下接口的實現:
class HandleModel : IModel { private var presenter: IPresenter? = null private var handler = Handler(Looper.getMainLooper()) override fun handleData(data: String) { if (TextUtils.isEmpty(data)) { return } handler.removeCallbacksAndMessages(null) // 延遲來模擬網絡或者磁盤操做 handler.postDelayed({ // 數據處理完成,通知 Presenter presenter?.dataHandled("handled data: $data") }, 3000) } override fun clearData() { handler.removeCallbacksAndMessages(null) // 數據清理完成,通知 Presenter presenter?.dataCleared() } override fun setPresenter(presenter: IPresenter) { this.presenter = presenter } }
Model
的實現和前面 MVC
中的實現基本一致,不過在 MVC
中 Model
直接操做 View
進行視圖展現,而在 MVP
裏,要通知 Presenter
去中轉。
這裏依舊是 Fragment
充當了 View
的角色,主要負責將 View
的事件傳遞給 Presenter
,以及接受到 Presenter
的數據進行界面更新。
class MVPFragment : Fragment(), IView { companion object { fun newInstance(): Fragment { val presenter = Presenter() val fragment = MVPFragment() val model = HandleModel() fragment.setPresenter(presenter) model.setPresenter(presenter) presenter.setModel(model) presenter.setView(fragment) return fragment } } var mpresenter: IPresenter? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.architecture, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) titleText.text = "MVP" edit.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { // 傳遞 文字修改 事件給 Presenter mpresenter?.onTextChanged(s.toString()) } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } }) clearText.setOnClickListener { // 傳遞按鈕點擊事件給 Presenter mpresenter?.onClearBtnClicked() } } override fun setPresenter(presenter: IPresenter) { this.mpresenter = presenter } // 展現數據處理中的視圖 override fun loading() { msgText.text = "handling data ..." } // 展現處理後的數據 override fun showData(data: String) { msgText.text = data } }
這裏 Presenter
的實現比較簡單,沒有太多的業務邏輯,實際應用中,這裏會進行業務邏輯的處理。
class Presenter : IPresenter { private var model: IModel? = null private var view: IView? = null override fun setModel(model: IModel) { this.model = model } override fun setView(view: IView) { this.view = view } override fun dataHandled(data: String) { view?.showData(data) } override fun dataCleared() { view?.showData("") } override fun onTextChanged(text: String) { view?.loading() model?.handleData(text) } override fun onClearBtnClicked() { model?.clearData() } }
MVVM
要解決的問題和 MVC
,MVP
大同小異:控制邏輯,數據處理邏輯和界面交互耦合,而且同時能將 MVC
中的 View
和 Model
解耦,還能夠把 MVP
中 Presenter
和 View
也解耦。
MVVM
架構裏,將邏輯,數據,界面的處理劃分爲三個部分,模型(Model)-視圖(View)-邏輯(ViewModel)。各個部分的功能以下:
Model
模型,負責數據的加載和存儲。View
視圖,負責界面的展現。ViewModel
控制器,負責邏輯控制。咱們能夠看到,MVP
中的各個角色劃分,和 MVC
,MVP
基本上類似,區別也是在於角色的通訊上。
咱們上面說到,在 MVP
中,就是 View
和 Model
不相互持有,都經過 Presenter
作中轉。這樣可使 View
和 Model
解耦。
而在 MVVM
中,解耦作的更完全,ViewModel
也不會持有 View
。其中 ViewModel
中的改動,會自動反饋給 View
進行界面更新,而 View
中的事件,也會自動反饋給 ViewModel
。
要達到這個效果,固然要使用一些工具輔助,比較經常使用的就是 databinding
。
在 MVVM 中,數據的流向是這樣的:
View
產生事件,自動通知給 ViewMode
,ViewModel
中進行邏輯處理後,通知 Model
更新數據,Model
更新數據後,通知數據結構給 ViewModel
,ViewModel
自動通知 View
更新界面。
這就是一個完整 MVVM
的數據流向。
MVVM
的實現會複雜一點,咱們先看下接口的定義:
// ViewModel 接口,定義了邏輯操做 interface IViewModel { fun setModel(model: IModel) fun handleText(text: String?) fun clearData() fun dataHandled(data: String?) fun dataCleared() } // 模型接口,定義了數據操做 interface IModel { fun setViewModel(viewModel: IViewModel) fun handleData(data: String?) fun clearData() }
MVVM
中的接口只定義了 ViewModel
和 Model
,沒有 View
接口,是由於 View
是經過 databind
和 ViewModel
的。
咱們再看看具體實現:
Model
的實現和上面基本一致,就是對數據的處理,處理完成後通知 ViewModel
。
class HandleModel : IModel { private var viewModel: IViewModel? = null private var handler = Handler(Looper.getMainLooper()) override fun handleData(data: String?) { if (TextUtils.isEmpty(data)) { return } handler.removeCallbacksAndMessages(null) // 延遲來模擬網絡或者磁盤操做 handler.postDelayed({ // 數據處理完成通知 ViewModel viewModel?.dataHandled("handled data: $data") }, 3000) } override fun clearData() { handler.removeCallbacksAndMessages(null) // 數據清理完成通知 ViewModel viewModel?.dataCleared() } override fun setViewModel(viewModel: IViewModel) { this.viewModel = viewModel } }
ViewModel
的實現要有些不一樣,咱們採用 databind
進行 ViewModel
和 View
的綁定。
其中會定義兩個變量,inputText
是和 EditText
雙向綁定的數據,handledText
是和 TextView
雙向綁定的數據。
當 EditText
中輸入的數據有變化,會通知到 inputText
註冊的監聽器中,而 handledText
值的改變,會自動顯示到界面上。
class ViewModel : IViewModel { private var model: IModel? = null // View 綁定的數據,inputText 和 handledText 更新後會自動通知 View 更新界面 var inputText: MutableLiveData<String> = MutableLiveData() var handledText: MutableLiveData<String> = MutableLiveData() init { // 註冊數據監聽,數據改變後通知 Model 去處理數據 inputText.observeForever { handleText(it) } handledText.value = "default msg" } override fun handleText(text: String?) { if (TextUtils.isEmpty(text)) { handledText.value = "default msg" return } handledText.value = "handle data ..." model?.handleData(text) } // 清空按鈕的點擊事件綁定 override fun clearData() { model?.clearData() } override fun setModel(model: IModel) { this.model = model model.setViewModel(this) } // Model 數據處理完成,設置 handledText 的值,自動更新到界面 override fun dataHandled(data: String?) { handledText.value = data } // Model 數據處理完成,設置 inputText 的值,自動更新到界面 override fun dataCleared() { inputText.value = "" } }
看一下 View
中的數據綁定。
class MVVMFragment : Fragment() { companion object { fun newInstance(): Fragment { return MVVMFragment() } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // 使用 databind 進行數據綁定 var binding: ArchitectureBindingBinding = DataBindingUtil.inflate(inflater, R.layout.architecture_binding, container, false) binding.lifecycleOwner = this val viewModel = ViewModel() viewModel.setModel(HandleModel()) binding.viewmodel = viewModel return binding.root } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <!--定義 View 中綁定的數據--> <data> <variable name="viewmodel" type="com.zy.architecture.mvvm.ViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" tools:context=".MainActivity"> <TextView android:id="@+id/titleText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="MVVM" /> <!--雙向綁定 inputText 到 EditText--> <EditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="50dp" android:text="@={viewmodel.inputText}" android:textColor="@android:color/darker_gray" /> <!--綁定 handledText 到 TextView--> <TextView android:id="@+id/msgText" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_marginTop="10dp" android:text="@{viewmodel.handledText}" android:textColor="@android:color/darker_gray" /> <!--綁定清空數據的點擊事件 到 TextView--> <TextView android:id="@+id/clearText" android:layout_width="match_parent" android:layout_height="30dp" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:gravity="center" android:onClick="@{() -> viewmodel.clearData()}" android:text="clear" android:textColor="@android:color/white" /> </LinearLayout> </layout>
經過上面的實現,當 EditText
中文字變化後,會自動修改 inputText
的值,觸發 inputText
監聽器,此時 ViewModel
將消息傳遞給 Model
進行處理,Model
數據處理完成後,通知 ViewModel
更新 handledText
的值,自動更新到界面上。
點擊清空按鈕時,自動調用綁定的點擊函數,通知 ViewModel
清空事件,ViewModel
將消息傳遞給 Model
進行數據清空,Model
數據處理完成後,通知 ViewModel
進行界面更新。
優勢:
MVP
的基礎上,MVVM
把 View
和 ViewModel
也進行了解耦缺點:
View
和 ViewModel
解耦,致使 Debug 時難以一眼看出 View
的事件傳遞上面的文章中,咱們介紹了 MVC,MVP,MVVM
三種架構模式,以及其簡單的實現。這裏咱們再回過頭思考一下,何時該使用架構模式呢?
架構模式可使代碼模塊清晰,職責分工明確,容易擴展,帶來的反作用就是會引入大量的接口,致使代碼文件數量激增。
咱們在最開始說過,架構模式是用來解決特定的問題的,若是特定的問題在目前階段不是問題,或者不是主要問題,那麼咱們能夠先不考慮使用架構模式。好比一個功能很是簡單,代碼量少,然後續又沒有擴展的需求,那咱們直接使用傳統方式進行開發,快速且清晰,徹底沒有必要爲了架構而架構。
對於在開始沒有考慮架構模式的代碼,後續慢慢去重構,也是一個好的選擇。
總結來講就是:架構雖好,可不要貪杯哦~
更多面試內容,面試專題,flutter視頻 全套,音視頻從0到高手開發。
關注 GitHub: https://github.com/xiangjiana/Android-MS
免費獲取面試PDF合集
免費提供簡歷修改建議,獲取大廠面試PDF