聊聊高煥堂老師的EIT架構(gòu)

今年春節(jié)的時(shí)候绰疤,我在51CTO上選中了新的課程铜犬,就是高煥堂老師的EIT架構(gòu)。由于自己對架構(gòu)比較感興趣轻庆,剛好又有這種題材的講座癣猾,因此很愉快的學(xué)習(xí)了一下,感覺也有很多收獲榨了,在這里簡單的記錄一下

什么是EIT

實(shí)際上這個(gè)名詞我也是偶然間得知的煎谍,就是自己在聽高老師講的jni系列課程的時(shí)候,反復(fù)的提到了EIT龙屉,當(dāng)時(shí)一臉迷茫呐粘,什么是EIT呢?于是百度了一下转捕。發(fā)現(xiàn)似乎并沒有相關(guān)的介紹作岖。在高老師的個(gè)人主頁上找了半天也沒有找到。剛好發(fā)現(xiàn)高老師講的架構(gòu)相關(guān)的課程五芝,就是介紹EIT的講座痘儡,好奇的就學(xué)起來了。

老實(shí)說剛開始聽前幾集講座的時(shí)候枢步,還是不太明白高老師要表達(dá)的意思沉删。雖然老是提到EIT渐尿,EIT,但從始至終也沒有說明什么是E矾瑰,什么是I砖茸,什么是T。我也是看到了講座中的一張圖后殴穴,才大概明白了EIT的含義凉夯,也就是下面的圖:

image.png

也就是說E&&I是在一個(gè)類中的,T是其子類采幌,這是一個(gè)基本的形式
另一種擴(kuò)展的形式是這樣的

image.png

和上面的圖稍微有些不同劲够,接口層interface被抽象出來了
這個(gè)圖已經(jīng)給出了EIT的英文名稱,即engine休傍,interface和tire征绎,但是這三者是什么關(guān)系呢?engine是引擎的意思磨取,interface是接口炒瘸,而tire是輪胎。一開始我沒有明白高老師的含義寝衫,尤其是EIT的基本型而言,T是子類拐邪,怎么能說輪胎是引擎的子類呢慰毅?隨著學(xué)習(xí)的逐漸深入,我終于明白扎阶,原來這里的EIT是按照擴(kuò)展型中的圖定義的汹胃,也就是一個(gè)汽車引擎,需要有四個(gè)輪胎構(gòu)成东臀,這里引擎并不直接依賴于具體的輪胎着饥,而是依賴于接口interface,而tire實(shí)現(xiàn)了這個(gè)接口惰赋,于是在編碼中就很有彈性了宰掉,即,我需要什么輪胎我就組裝什么輪胎就可以了赁濒,甚至在運(yùn)行的時(shí)候轨奄,我還可以換輪胎。這樣的設(shè)計(jì)拒炎,顯然代碼會更有彈性挪拟。

設(shè)計(jì)模式

上面的兩種形式,大概是高老師在設(shè)計(jì)模式的基礎(chǔ)上击你,高度抽象而來玉组。實(shí)際上上面的兩個(gè)圖谎柄,正是代表了設(shè)計(jì)模式中的兩種經(jīng)典的模型。

首先我想介紹一下設(shè)計(jì)模式中的精髓惯雳,也就是接口朝巫。為什么說接口很重要呢?因?yàn)榻涌诳梢宰寖蓚€(gè)銜接的模塊解耦吨凑,讓雙方互相不知道對方的存在捍歪,這在編碼架構(gòu)中,具有非常好的彈性鸵钝。

設(shè)計(jì)模式有很多種糙臼,但最核心的就是五大原則了。在這五大原則中恩商,我覺得最重要的变逃,就是最后一個(gè)原則,就是開閉原則怠堪,即對擴(kuò)展是開放的揽乱,對修改是封閉的。也就是說粟矿,如何判斷我們寫的架構(gòu)好不好呢凰棉?其實(shí)很簡單,如果追加一個(gè)類似的功能陌粹,可不可以撒犀?這就是擴(kuò)展型。在擴(kuò)展的同時(shí)是否必須需要破壞之前的代碼掏秩?還是直接追加新的文件就可以了或舞,以前的文件可以最大程度的保持不變?這就是封閉性蒙幻。如果你寫的架構(gòu)映凳,同時(shí)具備擴(kuò)展型和封閉性,那么就真的是一個(gè)好的架構(gòu)了邮破。

舉個(gè)例子诈豌,如果需要實(shí)現(xiàn)一個(gè)架構(gòu),小明每天騎車上班决乎,我們應(yīng)該如何設(shè)計(jì)呢队询?
我想最直觀的設(shè)計(jì)就是下圖了

image.png

這實(shí)在是太簡單了,剛學(xué)會編程的人构诚,大概也可以寫的出來這個(gè)代碼蚌斩。
我們簡單的寫一下這個(gè)代碼評估一下

class Person {
    void take(Bike* bike);
};

class Bike {

};

int main(int argc, char* argv) {
    Person* person = new Person();
    Bike* bike = new Bike();
    person->take(bike);
    return 0;
}

這真的不是很難。
該如何評估這個(gè)架子是否好呢?就用上面的兩個(gè)法則送膳,其一员魏,檢驗(yàn)是否有擴(kuò)展性,比如現(xiàn)在提出一個(gè)新需求叠聋,小明坐公交上班撕阎,這個(gè)架構(gòu)是否也同樣適用?當(dāng)然了可以適用碌补,只需要添加一個(gè)Bus類虏束,并且將Person類中take的參數(shù),改為Bus* bus就可以了厦章。其二镇匀,檢驗(yàn)是否是封閉的,我們?yōu)榱藬U(kuò)展新的需求袜啃,不得不修改已經(jīng)寫好的類中的代碼汗侵,即改變了Person中方法的參數(shù),這顯然不滿足封閉性群发。
特別的晰韵,如果我需要增加更多的交通工具,Person類就要不斷的修改熟妓,顯然雪猪,這個(gè)架構(gòu)設(shè)計(jì),smell bad起愈。

為什么這兩個(gè)特性都至關(guān)重要呢浪蹂?擴(kuò)展性就不必多說了,如果一個(gè)系統(tǒng)一點(diǎn)點(diǎn)擴(kuò)展性都沒有告材,顯然不會是一個(gè)很好的系統(tǒng)。為什么我們需要保持封閉性呢古劲?因?yàn)槲覀儾环忾]就意味著之前的代碼需要修改斥赋,那之前的一些工作無疑就白做了。比如Person類測試已經(jīng)充分驗(yàn)證产艾,完全沒有問題疤剑,可以給用戶使用,但是為了擴(kuò)展一個(gè)新的功能闷堡,我們不得不修改Person類隘膘,這樣之前的測試結(jié)果又要重來一遍,誰知道你引入的新的代碼杠览,會不會引起新的bug呢~

進(jìn)一步思考弯菊,為何我們的設(shè)計(jì)會破壞了開閉原則呢?就是因?yàn)槲覀冏尵唧w的東西Person踱阿,依賴于了具體的東西Bike了管钳。也就是兩個(gè)具體的東西耦合在了一起钦铁,因此Bike的改變必然會引起Person的改變。正確的做法才漆,應(yīng)該是依賴于抽象牛曹!因此我們要從交通工具中找到共通點(diǎn),從而抽象出抽象的接口

image.png

好了醇滥,這樣一來黎比,Person這個(gè)具體的東西,依賴于Traffic這個(gè)接口鸳玩,那么Bike的改變就不會引起Person的改變了
簡單的代碼如下

class Traffic;

class Person {
    void take(Traffic* trafic);
};

class Traffic {

};

class Bike : public Traffic {

};

class Bus : public Traffic {

};

int main(int argc, char* argv[]) {
    Person* person = new Person();
    Traffic* traffic = new Bike();
    person->take(traffic);
}

這樣的設(shè)計(jì)阅虫,顯然比剛才的設(shè)計(jì)就改良了不少,如果你還想擴(kuò)展新的交通工具怀喉,只要做相應(yīng)的子類就可以了书妻,這個(gè)擴(kuò)展,也不會引起Person類的修改躬拢,完全符合設(shè)計(jì)模式的原則躲履,真的很不錯(cuò)。

說到這里聊闯,我們其實(shí)就描述了一個(gè)設(shè)計(jì)模式:策略模式工猜。什么是策略模式呢?我們?nèi)ド习鄬?shí)際上是一種策略菱蔬,也就是這里的traffic接口篷帅,而具體的策略,比如是騎自行車拴泌,還是做公交車之類的由子類決定魏身。

EIT與設(shè)計(jì)模式

介紹完設(shè)計(jì)模式,特別是策略模式蚪腐,我們可以在EIT中找到策略模式的影子箭昵。E可以看做是Person,I可以看做是Traffic接口回季,而Bike以及Bus家制,就是具體的T。所以擴(kuò)展的EIT模式泡一,就可以看做是設(shè)計(jì)模式中的策略模式颤殴。

對于標(biāo)準(zhǔn)的EIT模型,設(shè)計(jì)模式中也有與其相對應(yīng)的一種鼻忠,即模板模式涵但。模板模式的應(yīng)用場景是這樣的,做一件事,可能分為幾個(gè)步驟贤笆,但是在做具體的步驟的時(shí)候蝇棉,不同的用戶做法不同,我們將這些具體的步驟做成接口芥永,讓用戶在實(shí)現(xiàn)子類中實(shí)現(xiàn)篡殷。比如,我們在排序的時(shí)候需要知道如何判斷兩個(gè)數(shù)的大小埋涧,這個(gè)具體的算法板辽,由用戶決定,因此做成接口棘催。用戶在準(zhǔn)備排序時(shí)劲弦,只需要提供如何判斷兩個(gè)數(shù)大小的方法就可以,至于如何排好序醇坝,基類就已經(jīng)實(shí)現(xiàn)好了邑跪,用戶不需要知道。

因此從這里看來呼猪,EIT的基本形式和擴(kuò)展形式画畅,實(shí)際上就對應(yīng)了設(shè)計(jì)模式中的兩種經(jīng)典的模式模板模式以及策略模式。讓我們繼續(xù)挖掘一下這兩個(gè)形式宋距≈狨猓基本形式是E&&I做在了一起,即在一個(gè)類中谚赎,而T繼承了I淫僻,這就是一個(gè)典型的繼承關(guān)系,也就是is-a的關(guān)系壶唤。而擴(kuò)展形式是E有一個(gè)接口I雳灵,T實(shí)現(xiàn)了接口I,這就是一個(gè)has-a的關(guān)系闸盔。這兩種關(guān)系各有利弊细办。設(shè)計(jì)模式中的建議,是讓我們盡量多用組合的方式蕾殴,即has-a的關(guān)系,而少用繼承的關(guān)系岛啸,即用組合來替代繼承钓觉。這樣做的好處時(shí),組合關(guān)系在運(yùn)行時(shí)是可以替換的坚踩。比如小明騎車上班荡灾,在中間突然想換公交車了,這也是完全可以的。

內(nèi)容與形式

我們說EIT有兩種形式批幌,基本形式和擴(kuò)展形式础锐,什么是形式呢?形式就是一種套路荧缘。高老師的意思是我們需要編碼的任何內(nèi)容都可以放在這個(gè)形式中皆警。你看,這里就提到了內(nèi)容和形式截粗。我們需要編碼的信姓,就是內(nèi)容,EIT就是形式绸罗,也就是意推,我們需要編碼的任何東西,都可以以EIT的形式呈現(xiàn)珊蟀。

比如剛才提到的小明騎車上班菊值,就是內(nèi)容,我們剛才用策略模式實(shí)現(xiàn)育灸,即EIT的擴(kuò)展型實(shí)現(xiàn)腻窒,就是一種形式。也就是我們用EIT的形式描扯,實(shí)現(xiàn)了小明騎車上班的內(nèi)容定页。

那么,真的所有復(fù)雜的代碼架構(gòu)绽诚,都可以通過EIT的形式展示嗎典徊?實(shí)際上是可以的,但絕不僅僅是一種形式恩够,復(fù)雜代碼架構(gòu)卒落,是由EIT這種簡單的形式組合而成。

事實(shí)上蜂桶,這里蘊(yùn)含的思想非常重要:任何復(fù)雜的東西都是由簡單的東西堆砌而成儡毕。所以在拿到一個(gè)復(fù)雜的架構(gòu)的時(shí)候,我們需要將他首先拆解成幾個(gè)簡單東西的組合扑媚,有的時(shí)候簡單的東西還需要繼續(xù)拆解腰湾。而拆解到最后的功能或者功能組,也就是內(nèi)容疆股,都可以通過EIT這種形式展示出來费坊,最后,我們將這些EIT的形式組合到一起旬痹,ok附井,復(fù)雜的架構(gòu)就開發(fā)出來了讨越。

我覺得這種思想也體現(xiàn)了軟件架構(gòu)設(shè)計(jì)的重要思路。
因此拿到一個(gè)需求永毅,我們首先需要將需求分解把跨,再提取出接口,分的好沼死,接口設(shè)計(jì)的好着逐,架構(gòu)就越好。

強(qiáng)龍不壓地頭蛇

高老師進(jìn)一步提出了強(qiáng)龍不壓地頭蛇的思想漫雕。什么是強(qiáng)龍滨嘱?強(qiáng)龍做的就是E&&I,什么是地頭蛇浸间?地頭蛇做的就是T
說的直觀一點(diǎn)太雨,強(qiáng)龍就是做框架設(shè)計(jì)的,而地頭蛇魁蒜,就是做定制化開發(fā)的囊扳。

比如Android,谷歌的程序員們兜看,就是強(qiáng)龍锥咸,他們負(fù)責(zé)做框架的開發(fā),他們將功能與任務(wù)進(jìn)行分解细移,并且流出了必要的接口I搏予,比如Activity中流出了接口OnCreate,OnDestroy等等弧轧。而我們這些程序開發(fā)者雪侥,就是要實(shí)現(xiàn)強(qiáng)龍們?yōu)槲覀冊O(shè)計(jì)好的接口,做定制化的開發(fā)精绎。這樣速缨,就產(chǎn)生了形形色色的不同的Android應(yīng)用。

因此架構(gòu)師們的核心工作就是代乃,將系統(tǒng)進(jìn)行拆解旬牲,設(shè)計(jì)出接口I,接口的設(shè)計(jì)搁吓,體現(xiàn)了一個(gè)架構(gòu)師的能力原茅,接口設(shè)計(jì)的好,地頭蛇們開發(fā)的就會非常開心堕仔。

尾聲

好了擂橘,對于高老師的這套架構(gòu)講座,就暫時(shí)總結(jié)到這里了贮预。
我覺得自己的收獲還是很大的贝室。高老師提出的EIT的思路確實(shí)很有借鑒意義。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仿吞,一起剝皮案震驚了整個(gè)濱河市滑频,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唤冈,老刑警劉巖峡迷,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绘搞,死亡現(xiàn)場離奇詭異夯辖,居然都是意外死亡董饰,警方通過查閱死者的電腦和手機(jī)卒暂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門也祠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人堪旧,你說我怎么就攤上這事崎场∷熘” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵螃宙,是天一觀的道長谆扎。 經(jīng)常有香客問我堂湖,道長,這世上最難降的妖魔是什么无蜂? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任训桶,我火速辦了婚禮酣倾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘午绳。我一直安慰自己箱叁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布惕医。 她就那樣靜靜地躺著耕漱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抬伺。 梳的紋絲不亂的頭發(fā)上螟够,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音峡钓,去河邊找鬼妓笙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛能岩,可吹牛的內(nèi)容都是我干的寞宫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼拉鹃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了膏燕?” 一聲冷哼從身側(cè)響起钥屈,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤篷就,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后竭业,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體智润,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年未辆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了做鹰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肯腕,死狀恐怖姊途,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贡茅,我是刑警寧澤顶考,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站渊季,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏病涨。R本人自食惡果不足惜赎懦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一当悔、第九天 我趴在偏房一處隱蔽的房頂上張望盲憎。 院中可真熱鬧饼疙,春花似錦、人聲如沸慕爬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽医窿。三九已至磅甩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間姥卢,已是汗流浹背更胖。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隔显,地道東北人却妨。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像括眠,于是被迫代替她去往敵國和親彪标。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容