MVP那些事兒 (3)……在Android中使用MVC(上)

為什么要先介紹MVC亲雪?

如果你要想更佳深刻的理解MVP跑揉,并在實(shí)際開(kāi)發(fā)中靈活的應(yīng)用锅睛,那么就要先了解它的低配版MVC,他倆只是一步之遙历谍,先了解MVC再學(xué)習(xí)MVP现拒,MVP的優(yōu)勢(shì)才能凸顯出來(lái),這樣連貫性的學(xué)習(xí)才會(huì)加深對(duì)MVP的理解望侈。

目錄

MVP那些事兒(1)……用場(chǎng)景說(shuō)話

MVP那些事兒(2)……MVC架構(gòu)初探

MVP那些事兒(3)……在Android中使用MVC(上)

MVP那些事兒(4)……在Android中使用MVC(下)

MVP那些事兒(5)……中介者模式與MVP的關(guān)系【知識(shí)點(diǎn)】

MVP那些事兒(6)……MVC變身為MVP

MVP那些事兒(7)……Kotlin實(shí)現(xiàn)MVP【知識(shí)點(diǎn)】

MVP那些事兒(8)……當(dāng)MVP遇到Lifecycle【知識(shí)點(diǎn)】

MVP那些事兒(9)……探究MVP的最佳實(shí)踐

MVP那些事兒(10)……MVVM雙向綁定

MVP那些事兒(11)……基于MVVM的Architecture Components

回顧MVP那些事兒(2) 初探MVC架構(gòu)的內(nèi)容:

MVC的作用印蔬?它是設(shè)計(jì)模式嗎?是框架嗎脱衙?是架構(gòu)嗎侥猬?
MVC各個(gè)層的定義和職責(zé)

通過(guò)上一篇的內(nèi)容,大家也對(duì)MVC已經(jīng)有了一個(gè)大致的了解捐韩,在開(kāi)啟這一章內(nèi)容前退唠,希望大家能先閱讀上一篇的內(nèi)容,否則可能會(huì)“斷片”荤胁。
在上一篇中瞧预,我們?cè)敿?xì)的介紹了MVC三個(gè)層的基本職責(zé),我們?cè)倩仡櫼幌逻@三個(gè)“片段”:

Model層

1、JavaBean不是Model垢油,但Model也可以包含JavaBean的職責(zé)盆驹,但不是必須的。
2秸苗、Model是用來(lái)處理數(shù)據(jù)的,如獲取數(shù)據(jù)(本地或者服務(wù)端)召娜,數(shù)據(jù)處理,如CURD惊楼。

View層

1玖瘸、它的主要職責(zé)為呈現(xiàn)Model的數(shù)據(jù)、主動(dòng)詢問(wèn)狀態(tài)或被動(dòng)的監(jiān)聽(tīng)
2檀咙、通知控制器Controller去處理一些事情
3雅倒、接收Controller,編輯自己與Model無(wú)關(guān)的狀態(tài)

Controller

1弧可、接收View的操作蔑匣,并轉(zhuǎn)調(diào)給Model
2、改變View的狀態(tài)

同時(shí)還遺留了兩個(gè)問(wèn)題:

1棕诵、如何把這三個(gè)片段組裝起來(lái)裁良?在Android里怎么寫(xiě)?
2校套、view在執(zhí)行tasksRepository.getTaskCache()時(shí)价脾,是怎么知道tasksRepository數(shù)據(jù)已經(jīng)準(zhǔn)備好了呢?怎么通知view的笛匙?

把片段“組合”起來(lái)

在模式設(shè)計(jì)時(shí)侨把,我們會(huì)通過(guò)關(guān)系圖來(lái)反映對(duì)象間的關(guān)系,如下圖:

MVC架構(gòu)圖

這是一張非常經(jīng)典的MVC架構(gòu)圖(手殘妹孙,有點(diǎn)丑……)秋柄,相信大家對(duì)這張圖已經(jīng)不陌生了,OK蠢正,這張圖我先放下不表骇笔,因?yàn)榭紤]到我們介紹的是架構(gòu),本身是抽象的嚣崭,加上如此抽象的圖笨触,怕是不能好好的切入,所以我想盡可能的巨像化這個(gè)過(guò)程有鹿,當(dāng)大家有一個(gè)清晰的理解后旭旭,再回過(guò)頭來(lái)重新審視它。我本來(lái)是想放在文章的后半段祭出這張圖的葱跋,但想了想有點(diǎn)不妥持寄,原因是我們上期已經(jīng)通過(guò)一整篇用來(lái)初探MVC源梭,也該把MVC的架構(gòu)圖貼出來(lái)應(yīng)一應(yīng)景了……

image

那么MVC這三者的關(guān)系究竟是怎樣的呢?

我們依舊通過(guò)現(xiàn)實(shí)中的場(chǎng)景來(lái)描述一下MVC三者的關(guān)系稍味,讓大家對(duì)這三者的關(guān)系有一個(gè)初期的直觀的理解废麻,起到一個(gè)拋磚引玉的效果,廢話不多模庐,場(chǎng)景開(kāi)始烛愧。

場(chǎng)景

想必大家都租過(guò)房子,有當(dāng)租客的體驗(yàn)掂碱,也有一部分人可能還有當(dāng)過(guò)過(guò)房東經(jīng)驗(yàn)怜姿,在當(dāng)下的社會(huì)中,房屋中介是我們租房找房必不可少的環(huán)節(jié)疼燥,我相信大部分人都和中介打過(guò)交道沧卢,咳咳,那我們就還原一下租房的過(guò)程醉者,

首先但狭,確定角色

在這個(gè)場(chǎng)景里包含了三個(gè)角色,租客撬即、中介立磁、和房東,

其次剥槐,選擇角度

我們從租戶的角度描述一下租房的場(chǎng)景唱歧,只考慮正向流程。

再次才沧,場(chǎng)景描述

租客要先找到中介并描述自己需要的房子迈喉,中介接到需求后绍刮,通過(guò)篩選發(fā)現(xiàn)有一個(gè)房東很適合温圆,于是中介開(kāi)始與這個(gè)房東接觸,詢問(wèn)一些和房子租金相關(guān)的事宜孩革,如果中介覺(jué)的合適岁歉,他會(huì)把反饋告知客戶,如果客戶也覺(jué)的合適膝蜈,中介就會(huì)把租客和房東約在店里進(jìn)行更進(jìn)一步的協(xié)商锅移,如果能促成合同,那么到此為止中介完成了現(xiàn)階段的工作饱搏,剩下的事情非剃,比如租客向房東每個(gè)季度繳納房租,或者詢問(wèn)房東家里電器的使用方式推沸,亦或者房東詢問(wèn)房客租約到期是否續(xù)租等等备绽,這些溝通都可以拋開(kāi)中介去完成券坞,也就是說(shuō),不一定需要中介作為他們之間溝通的橋梁肺素,但也并不意味著中介在以后的場(chǎng)景中是不可用的恨锚,比如,在租房過(guò)程中有一些事情租客和房東有分歧倍靡,也可以通過(guò)中介來(lái)進(jìn)行協(xié)調(diào)和溝通猴伶。

還有一種中介的形式是,租客和房東是見(jiàn)不到彼此的塌西,全程由中介負(fù)責(zé)他挎,這種房叫托管房,租客不知道房東是誰(shuí)捡需,房東也不知道租客是誰(shuí)雇盖,合同都和中介簽,我們現(xiàn)在不討論這種情況栖忠。

來(lái)個(gè)圖描述一下上訴的情景

好隨便的圖

這張圖的目的一來(lái)是復(fù)述一下上面的場(chǎng)景描述崔挖,二來(lái)是讓大家直觀的看到它們?nèi)呓换サ囊粋€(gè)關(guān)系。

中介庵寞、租客狸相、房東,把他們和MVC的三個(gè)角色關(guān)聯(lián)起來(lái)

通過(guò)上訴場(chǎng)景的描述捐川,和前一篇帖子中介紹的MVC各個(gè)對(duì)象的職責(zé)脓鹃,想必他們到底誰(shuí)是誰(shuí)一目了然,我們?cè)囍P(guān)聯(lián)一下這幾個(gè)對(duì)象

首先看中介古沥,他負(fù)責(zé)了執(zhí)行租客的招租要求瘸右,并告知房東這些要求,也就是說(shuō)他作為中介向房東轉(zhuǎn)告租客的需求岩齿,那中介就是我們的Controller太颤。

再次看租客,他是需求的發(fā)出者盹沈,他比其他幾個(gè)對(duì)象更積極的提出需求龄章,就好比View,總是再向Controller提出需求乞封,也會(huì)更主動(dòng)的向Model詢問(wèn)狀態(tài)做裙,就像租客一樣,遇到問(wèn)題肃晚,要么找中介锚贱,要么去詢問(wèn)房東,所以关串,在這里把租客看作是View更加的貼切拧廊。

最后只剩下房東這個(gè)角色了杂穷,最后的Model就分配給房東吧。

接下來(lái)我們用MVC的方式來(lái)梳理一下中介卦绣、租客耐量、房東的關(guān)系

1、View To Controller 求租房


image

2滤港、Controller To Model 詢問(wèn):出租嗎廊蜒?


image

3、Controller To View 告知:找到房源
image

4溅漾、View To Model 單聊:能便宜嗎山叮?


image

5、Model To View 單聊:沒(méi)門兒添履!
image

上面這五張圖屁倔,是把MVC三個(gè)對(duì)象間的關(guān)系,以及案例中的業(yè)務(wù)流程做了一個(gè)“融合”暮胧,是一個(gè)抽象到具象的“融合”锐借,架構(gòu)圖中這些帶箭頭的線,是用來(lái)解釋對(duì)象間關(guān)系的往衷,無(wú)非就是那些誰(shuí)依賴誰(shuí)的解釋钞翔,我同時(shí)又在線上加入了一些事件,是希望能把上面具象的問(wèn)題引到抽象的架構(gòu)中來(lái)席舍,在實(shí)際中布轿,這樣的融合是不符合常理的,比如你無(wú)法用單個(gè)業(yè)務(wù)場(chǎng)景去定義對(duì)象間的依賴關(guān)系来颤,比如View To Controller汰扭,難道只有求租房這個(gè)場(chǎng)景才可以這么用嗎?顯然不是的福铅,包括各個(gè)角色中括號(hào)后面的稱呼萝毛。所以,為了解決通用性的問(wèn)題本讥,人們把這樣的具象問(wèn)題抽象成了一種依賴關(guān)系珊泳。

架構(gòu)是藍(lán)圖鲁冯,抽象的存在拷沸,而框架是具象的,它是為了解決具體某一類問(wèn)題而設(shè)計(jì)的。

MVC架構(gòu)圖是怎么來(lái)的薯演?拋去具象撞芍,看本質(zhì)

具象到抽象三連圖

抽象到最后就是我們開(kāi)篇的第一張圖。

在某些場(chǎng)合里跨扮,需要我們?nèi)ソ榻B我們的軟件架構(gòu)序无,這就需要我們具備描述架構(gòu)的能力验毡,我覺(jué)的可以先描述一下具象的問(wèn)題,再描述向上抽離的步驟帝嗡,最后陳述抽象的產(chǎn)物晶通,也就是我們的架構(gòu),是一個(gè)不錯(cuò)的思路哟玷。

應(yīng)用到實(shí)際中

通過(guò)上面大篇幅的拋磚引玉狮辽,相信大家對(duì)MVC的架構(gòu)有了一個(gè)初步的認(rèn)識(shí),那么接下來(lái)我們開(kāi)始真正的使用巢寡,還記得上一篇我們使用了一個(gè)需求:

需求:列表加載數(shù)據(jù)并且展示

我們依舊使用這個(gè)需求喉脖,因?yàn)榍懊娑x好了三個(gè)層的類,接下來(lái)要做的是按照MVC的架構(gòu)把他們拼裝起來(lái):

在Android中使用

開(kāi)始加入到實(shí)際開(kāi)發(fā)階段抑月,我們先創(chuàng)建一個(gè)Activity

public class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

緊接著树叽,我們把上一篇定義好的三個(gè)MVC對(duì)象也加入進(jìn)來(lái)

Model :TasksRepository

    /**我是一個(gè)Model**/
    public class TasksRepository {
        //從服務(wù)器請(qǐng)求獲取數(shù)據(jù)
        void getTasks() {}
        //從內(nèi)存緩存獲取數(shù)據(jù)
        Data getTaskCache() {}
        //從磁盤緩存獲取數(shù)據(jù)
        Data getTaskDiskCache(){}
        //保存一條數(shù)據(jù)
        boolean saveTask(Task task) {}
        //對(duì)數(shù)據(jù)進(jìn)行排序
        Data orderData(Data data, int orderType){}
    }

View :TasksView

    /**我是一個(gè)View**/
    public class TaskView {
        //當(dāng)列表初始化后,告訴控制器該加載數(shù)據(jù)了
        void viewCreate() {}
        //更新列表
        void upDateList() {}
        //just for ui
        void beginLoadData(){}
    }

Controller :TasksController

/**我是一個(gè)Contorller**/
public class TasksController {
    void loadNomData() {}
}

現(xiàn)在我們有了Activity谦絮,TasksRepository题诵、TasksView、TasksController

有了這些對(duì)象层皱,我們就可以進(jìn)行組合了仇轻,我們從什么地方下手呢?也許我們可以從MVC的架構(gòu)圖中得到些啟示奶甘,雖然架構(gòu)圖很簡(jiǎn)單篷店,但是有箭頭,有方向臭家,在UML中疲陕,這些線和箭頭便是記錄著對(duì)象間的關(guān)系:

image

按照架構(gòu)圖的提示,我們?yōu)門asksRepository钉赁、TasksView蹄殃、TasksController這三個(gè)類梳理了一個(gè)大致的依賴關(guān)系,同時(shí)MainActivity被撂到了一邊你踩,并不是它和這三個(gè)對(duì)象沒(méi)有關(guān)系诅岩,而是它現(xiàn)在還不能直接用,它需要變一下带膜,為什么這么說(shuō)呢吩谦,來(lái)看例子:

public class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化MVC
        TasksController controller = new TasksController();
        TasksView view = new TasksView();
        TasksRepository model = new TasksRepository();
        //依賴關(guān)系
        controller.setView(view);
        view.setController(controller);
        view.setModel(model);
        model.setController(controller);
        model.setView(view)
        //執(zhí)行業(yè)務(wù)
        controller.loadNomData();
    }
}

我承認(rèn),我又開(kāi)始拋磚引玉了膝藕,從這種寫(xiě)法來(lái)看式廷,Activity到是像MVC的容器,它包含了MVC這三個(gè)對(duì)象芭挽,這么寫(xiě)有問(wèn)題嗎滑废?在繼續(xù)之前蝗肪,引用一個(gè)概念,Is a…… and Has a

Is a 與 Has a

翻譯過(guò)來(lái)蠕趁,就是薛闪,我是什么,和我有什么

Is a 我是什么俺陋?

//我是什么動(dòng)物逛绵?我是一只貓
class Animal implments Cat {
    //喵喵叫
    void miaomiao();
}

Has a 我有什么?

//我有什么動(dòng)物倔韭?我有一只貓术浪,一只狗,一只豹子
class Animal{
    public Animal(Cat cat) {
        //來(lái)只貓
        this.cat = cat;
        //來(lái)個(gè)豹子
        this.baozi = new Baozi();
    }
    //來(lái)只狗
    void setDog(Dog dog) {
        this.dag = dog;
    }
}

相信大家看出了其中的差別寿酌,回過(guò)頭我們看一下MainActivity胰苏,它是什么,它又有什么醇疼,首先它是一個(gè)Activity硕并,其次,它有TasksRepository秧荆、TasksView倔毙、TasksController這三個(gè)對(duì)象,重點(diǎn)在Has a上乙濒,像這樣的依賴耦合度是非常高的陕赃,基本沒(méi)有擴(kuò)展的余地,為了降低耦合颁股,可不可以讓MainActivity少幾個(gè)Has a么库?當(dāng)然可以。

我是一只貓甘有,我有一只狗和豹子

//我是什么動(dòng)物诉儒?我是一只貓
class Animal implments Cat {
    //喵喵叫
    void miaomiao();
    public Animal() {
        //來(lái)個(gè)豹子
        this.baozi = new Baozi();
    }
    //來(lái)只狗
    void setDog(Dog dog) {
        this.dag = dog;
    }
}

所以我們讓MainActivity變一下身,從MVC這三個(gè)對(duì)象TasksRepository亏掀、TasksView忱反、TasksControlle中選一個(gè)變,這樣強(qiáng)耦合的個(gè)數(shù)從3個(gè)變成了2個(gè)滤愕,那么選誰(shuí)好呢温算?
目前主流的是選擇View,和選擇Controller该互,大家都是從業(yè)務(wù)的角度出發(fā)去選擇米者,首先選擇View,因?yàn)锳ctivity里包含了布局對(duì)象宇智,所以因?yàn)椤半x得近”讓Activity變成View蔓搞,選擇Controller的是因?yàn)锳ctivity本身的生命周期可以很好的用來(lái)控制業(yè)務(wù)流程,這樣對(duì)Controller來(lái)說(shuō)更加有利随橘,說(shuō)實(shí)話喂分,我并沒(méi)有深挖其中哪一個(gè)更好,因?yàn)槲矣X(jué)的這兩種方案都有他們的側(cè)重机蔗,還是要從實(shí)際的業(yè)務(wù)角度去考慮問(wèn)題蒲祈,那我們突發(fā)奇想讓Activity既是View,又是Controller呢萝嘁?這不就解決變成誰(shuí)的問(wèn)題了嗎梆掸?個(gè)人覺(jué)的還是不要的好,你總不能介紹自己的時(shí)候說(shuō):大家好牙言,我是貓酸钦,也是狗,我是男的也是女的咱枉,我相信到時(shí)候場(chǎng)面一定很混亂卑硫,我們還是保持類的職責(zé)單一性吧。但沒(méi)準(zhǔn)那天變成Model玩一下也可以的吧蚕断,所以說(shuō)欢伏,目前我先從變成View來(lái)開(kāi)始,后續(xù)的章節(jié)我們會(huì)講解變成Controller該怎么辦亿乳。

更新UML


image

同時(shí)更新一下代碼硝拧,我們讓MainActivity實(shí)現(xiàn)一個(gè)TasksView,賦予它View的職責(zé)

public class MainActivity extends AppCompatActivity implments TasksView{
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //略……
    }
}

確定了Activity葛假,我們才開(kāi)始了第一步河爹,接下來(lái)我們就要看一下Controller的初始化,在此之間需要引用一個(gè)概念桐款,依賴注入咸这。

依賴注入

什么是依賴注入?首先解釋一下什么是依賴魔眨,看下面的代碼:

class Animal{
    public Animal(Cat cat) {
        //來(lái)只貓
        this.cat = cat;
        //來(lái)個(gè)豹子
        this.baozi = new Baozi();
    }
    //來(lái)只狗
    void setDog(Dog dog) {
        this.dag = dog;
    }
    //貓貓叫一下
    void miaomiao() {
        cat.miaomiao();
    }
    //豹子叫一下
    void aoao() {
        baozi.called();
    }
}

aoao這個(gè)方法內(nèi)部媳维,調(diào)用了baozi這個(gè)對(duì)象叫的方法called(),也就是說(shuō)遏暴,首先Animal這個(gè)對(duì)象自己是不會(huì)叫的侄刽,他需要依賴于Baozi對(duì)象,Animal依賴Baozi去叫朋凉,這個(gè)依賴就是Baozi州丹,我們看到Baozi對(duì)象的初始化,是在Animal構(gòu)造器中new出來(lái)的。再看一下miaomiao方法內(nèi)部墓毒,依舊是依賴于cat的miaomiao方法去叫吓揪,而這個(gè)cat對(duì)象是從構(gòu)造函數(shù)傳進(jìn)來(lái)的,baozi和cat同樣是Animal的依賴所计,但獲得的途徑不同柠辞,cat的獲得途徑就是注入,而它又是依賴主胧,所以我們稱之為依賴注入叭首,依賴注入的形式除了通過(guò)構(gòu)造器參數(shù)外,還可以通過(guò)普通方法傳入踪栋,如上面的setDog方法焙格,我們注入了一只Dog。

依賴注入的好處

說(shuō)到依賴注入的好處夷都,不得不提Java的面向?qū)ο蟮奶匦灾械亩鄳B(tài)眷唉,舉個(gè)例子,上面的代碼中的Cat可以是一個(gè)接口损肛,我們?cè)谑褂肁nimal類前厢破,可以確定一下Cat的實(shí)現(xiàn)類,根據(jù)業(yè)務(wù)需求治拿,接收到的可能是公貓摩泪,也可能是母貓,可能是美短劫谅,也可能是英短(貓的品種)见坑,如果我們把Cat的依賴放在Animal中去初始化,那么根據(jù)業(yè)務(wù)的變化捏检,可能需要頻繁的更改Animal類荞驴。第二點(diǎn)好處,當(dāng)Cat的構(gòu)造器發(fā)生變化贯城,Animal也需要更改Cat熊楼,如果Cat需要另外的依賴,比如貓需要貓糧它才能活下去能犯,那么Animal也要間接的依賴貓糧鲫骗,對(duì)象間的耦合性就暴露了出來(lái),所以從外部傳入的依賴踩晶,Animal無(wú)需關(guān)心依賴的依賴执泰。

看來(lái)依賴注入是非常好的設(shè)計(jì)手段,那么回到上面的問(wèn)題渡蜻,Contorller的初始化术吝,我們知道Controller是依賴于View的计济,所以我們需要把View注入到Controller中去。

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排苍,通過(guò)構(gòu)造器注入
        TasksController controller = new TasksController(tasksView:this);
    }
}

通過(guò)依賴注入沦寂,我們把Controller和View的命運(yùn)綁定在了一起。
說(shuō)完了View -> Controller,我們還要解決Controller -> View,其實(shí)我們可以發(fā)現(xiàn)纪岁,Controller就是包含在View中的凑队,因?yàn)锳ctivity在上面已經(jīng)變身成了View则果,而Controller也在Activity中通過(guò)new的方式進(jìn)行了初始化幔翰,也就順理成章的成了View的依賴了,只不過(guò)它不是通過(guò)注入的方式進(jìn)入到View(MainActivity)中的西壮,那么有什么辦法可以做到這一點(diǎn)呢遗增?當(dāng)然有辦法了,介紹一下依賴注入的第三種方式:通過(guò)構(gòu)建一個(gè)Controller的工廠來(lái)負(fù)責(zé)生產(chǎn)Controller的實(shí)例款青,具體就不在這里細(xì)說(shuō)了做修,以后講到Dagger時(shí)可以和大家詳細(xì)討論。

Model的初始化

那么Model(TasksRepository)的初始化放在哪里去做呢抡草?以及它與Controller和View的關(guān)系又是怎樣的呢饰及?從MVC的架構(gòu)圖和框架的UML圖里可以得到答案,Controller和Model之間是一個(gè)單向的依賴康震,也就是Controller -> Model燎含,同時(shí)Model與View是一個(gè)雙向的依賴,

1腿短、Controller -> Model
2屏箍、Model -> View
3、View -> Model

我們只需滿足這三個(gè)條件橘忱,我們直接這樣赴魁,看代碼:

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,通過(guò)構(gòu)造器注入
        TasksController controller = new TasksController(tasksView:this);
        
        //初始化Model钝诚,Model -> View and View -> Model
        TasksRepository model = new TasksRepository(tasksView:this);
        
        //Controller -> Model
        model.setController(controller);
    }
}

首先在Activty中颖御,初始化Model,并將View注入到Model里凝颇,這樣潘拱,同時(shí)滿足了Model -> View 和 View -> Model,其次祈噪,通過(guò)model的setController方法將上面創(chuàng)建好的Controller注入到Model中泽铛,也就是滿足了Controller -> View 這個(gè)條件。

階段性總結(jié)

到此我們就完成了MVC片段的組合辑鲤,我們從頭再梳理一下這個(gè)過(guò)程

實(shí)現(xiàn)步驟:

1盔腔、Is View,Activity實(shí)現(xiàn)View

將Activity賦予View的職責(zé)。

2弛随、Controller -> View 瓢喉,在Activity中創(chuàng)建Controller的實(shí)例。

通知控制器Controller去處理一些事情
接收View的操作舀透,并轉(zhuǎn)調(diào)給Model

3栓票、View -> Controller,將View注入到Controller愕够。

接收Controller走贪,編輯自己與Model無(wú)關(guān)的狀態(tài)

4、Model -> View惑芭,在Activity中創(chuàng)建Model的實(shí)例坠狡。

主動(dòng)詢問(wèn)Model的狀態(tài),呈現(xiàn)Model的數(shù)據(jù)

5遂跟、View -> Model逃沿,將View注入到Model。

監(jiān)聽(tīng)Model的變化幻锁,如有變化通知View

6凯亮、Controller -> Model,將Contoller注入到View

監(jiān)聽(tīng)Model的變化哄尔,如果變化通知Controller

心路歷程

通過(guò)MVC的架構(gòu)圖假消,我們嘗試的設(shè)計(jì)了UML,并且通過(guò)Is a 究飞,Has a原則確定了View的歸屬置谦,其次,通過(guò)依賴注入原則亿傅,確定了依賴創(chuàng)建方式媒峡,再次,通過(guò)MVC的架構(gòu)圖與UML確立了Controller葵擎,View谅阿, Model這三者之間的關(guān)系,再結(jié)合依賴注入原則完成了整個(gè)框架的搭建酬滤。

總結(jié)

在之前的介紹MVC各個(gè)層的職責(zé)中签餐,“監(jiān)聽(tīng)”這個(gè)詞出現(xiàn)的頻率很高,在面向?qū)ο笳Z(yǔ)言的設(shè)計(jì)中盯串,“監(jiān)聽(tīng)”是一個(gè)動(dòng)作氯檐,與它相反的便是“獲取”這個(gè)動(dòng)作了。目前這個(gè)框架還是個(gè)雛形体捏,并沒(méi)有“監(jiān)聽(tīng)”的能力冠摄,同時(shí)包括各個(gè)層代碼的不完善糯崎,以及控制反轉(zhuǎn)等實(shí)際性內(nèi)容的缺失…… 本來(lái)想用一章來(lái)寫(xiě)完,但篇幅有些長(zhǎng)河泳,看來(lái)不得不分了沃呢。以前總覺(jué)的看別人的帖子挺快的,不一會(huì)兒就看完了拆挥,但真正自己去碼可是真的慢薄霜,主要是擔(dān)心描述的不夠清晰,擔(dān)心不能把自己的想法很清晰的表達(dá)出來(lái)纸兔,同時(shí)又擔(dān)心過(guò)于清晰的表達(dá)會(huì)不會(huì)又顯得啰里八嗦惰瓜,刪了改,改了刪的食拜,總之鸵熟,我會(huì)盡最大努力完成這個(gè)系列的副编,喜歡的就點(diǎn)個(gè)贊负甸,鼓勵(lì)鼓勵(lì)我。

最后的最后痹届,布置一個(gè)家庭作業(yè)呻待,看下面三張圖:

image

問(wèn)題1,圖一和圖二的區(qū)別队腐,以及圖二算不算MVC
問(wèn)題2蚕捉、MVC可以像圖三那樣去設(shè)計(jì)嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柴淘,一起剝皮案震驚了整個(gè)濱河市迫淹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌为严,老刑警劉巖敛熬,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異第股,居然都是意外死亡应民,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門夕吻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)诲锹,“玉大人,你說(shuō)我怎么就攤上這事涉馅」樵埃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵稚矿,是天一觀的道長(zhǎng)庸诱。 經(jīng)常有香客問(wèn)我悬钳,道長(zhǎng),這世上最難降的妖魔是什么偶翅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任默勾,我火速辦了婚禮,結(jié)果婚禮上聚谁,老公的妹妹穿的比我還像新娘母剥。我一直安慰自己,他們只是感情好形导,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布环疼。 她就那樣靜靜地躺著,像睡著了一般朵耕。 火紅的嫁衣襯著肌膚如雪炫隶。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天阎曹,我揣著相機(jī)與錄音伪阶,去河邊找鬼。 笑死处嫌,一個(gè)胖子當(dāng)著我的面吹牛栅贴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播熏迹,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼模软,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼受啥!你這毒婦竟也來(lái)了袖迎?” 一聲冷哼從身側(cè)響起猫牡,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捆昏,沒(méi)想到半個(gè)月后赚楚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屡立,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年直晨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膨俐。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勇皇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焚刺,到底是詐尸還是另有隱情敛摘,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布乳愉,位于F島的核電站兄淫,受9級(jí)特大地震影響屯远,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捕虽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一慨丐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泄私,春花似錦房揭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至咧纠,卻和暖如春蓬痒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漆羔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工梧奢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钧椰。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓粹断,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親嫡霞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345