(轉(zhuǎn))數(shù)據(jù)驅(qū)動(dòng)編程之表驅(qū)動(dòng)法

本文示例代碼采用的是c語(yǔ)言丧慈。

之前介紹過(guò)數(shù)據(jù)驅(qū)動(dòng)編程《什么是數(shù)據(jù)驅(qū)動(dòng)編程》析命。里面介紹了一個(gè)簡(jiǎn)單的數(shù)據(jù)驅(qū)動(dòng)手法。今天更進(jìn)一步,介紹一個(gè)稍微復(fù)雜鹃愤,更加實(shí)用的一點(diǎn)手法——表驅(qū)動(dòng)法簇搅。

關(guān)于表驅(qū)動(dòng)法,在《unix編程藝術(shù)》中有提到软吐,更詳細(xì)的描述可以看一下《代碼大全》馍资,有一章專門進(jìn)行描述(大概是第八章)。

簡(jiǎn)單的表驅(qū)動(dòng):

《什么是數(shù)據(jù)驅(qū)動(dòng)編程》中有一個(gè)代碼示例关噪。它其實(shí)也可以看做是一種表驅(qū)動(dòng)手法鸟蟹,只不過(guò)這個(gè)表相對(duì)比較簡(jiǎn)單,它在收到消息后使兔,根據(jù)消息類型確定使用調(diào)用什么函數(shù)進(jìn)行處理建钥。

復(fù)雜一點(diǎn)的表驅(qū)動(dòng):

考慮一個(gè)消息(事件)驅(qū)動(dòng)的系統(tǒng),系統(tǒng)的某一模塊需要和其他的幾個(gè)模塊進(jìn)行通信虐沥。它收到消息后熊经,需要根據(jù)消息的發(fā)送方,消息的類型欲险,自身的狀態(tài)镐依,進(jìn)行不同的處理。比較常見(jiàn)的一個(gè)做法是用三個(gè)級(jí)聯(lián)的switch分支實(shí)現(xiàn)通過(guò)硬編碼來(lái)實(shí)現(xiàn):

[cpp]?view plain?copy

switch(sendMode)??

{??

case:??

}??

switch(msgEvent)??

{??

case:??

}??

switch(myStatus)??

{??

case:??

}??

這種方法的缺點(diǎn):

1天试、可讀性不高:找一個(gè)消息的處理部分代碼需要跳轉(zhuǎn)多層代碼槐壳。

2、過(guò)多的switch分支喜每,這其實(shí)也是一種重復(fù)代碼务唐。他們都有共同的特性,還可以再進(jìn)一步進(jìn)行提煉带兜。

3枫笛、可擴(kuò)展性差:如果為程序增加一種新的模塊的狀態(tài),這可能要改變所有的消息處理的函數(shù)刚照,非常的不方便刑巧,而且過(guò)程容易出錯(cuò)。

4无畔、程序缺少主心骨:缺少一個(gè)能夠提綱挈領(lǐng)的主干啊楚,程序的主干被淹沒(méi)在大量的代碼邏輯之中。

用表驅(qū)動(dòng)法來(lái)實(shí)現(xiàn):

根據(jù)定義的三個(gè)枚舉:模塊類型檩互,消息類型特幔,自身模塊狀態(tài),定義一個(gè)函數(shù)跳轉(zhuǎn)表:

[cpp]?view plain?copy

typedef?struct??__EVENT_DRIVE??

{??

MODE_TYPE?mod;//消息的發(fā)送模塊??

EVENT_TYPE?event;//消息類型??

STATUS_TYPE?status;//自身狀態(tài)??

EVENT_FUN?eventfun;//此狀態(tài)下的處理函數(shù)指針??

}EVENT_DRIVE;??


EVENT_DRIVE?eventdriver[]?=//這就是一張表的定義闸昨,不一定是數(shù)據(jù)庫(kù)中的表蚯斯。也可以使自己定義的一個(gè)結(jié)構(gòu)體數(shù)組薄风。??

{??

????{MODE_A,?EVENT_a,?STATUS_1,?fun1}??

????{MODE_A,?EVENT_a,?STATUS_2,?fun2}??

????{MODE_A,?EVENT_a,?STATUS_3,?fun3}??

????{MODE_A,?EVENT_b,?STATUS_1,?fun4}??

????{MODE_A,?EVENT_b,?STATUS_2,?fun5}??


????{MODE_B,?EVENT_a,?STATUS_1,?fun6}??

????{MODE_B,?EVENT_a,?STATUS_2,?fun7}??

????{MODE_B,?EVENT_a,?STATUS_3,?fun8}??

????{MODE_B,?EVENT_b,?STATUS_1,?fun9}??

????{MODE_B,?EVENT_b,?STATUS_2,?fun10}??

};??


int?driversize?=?sizeof(eventdriver)?/?sizeof(EVENT_DRIVE)//驅(qū)動(dòng)表的大小??


EVENT_FUN?GetFunFromDriver(MODE_TYPE?mod,?EVENT_TYPE?event,?STATUS_TYPE?status)//驅(qū)動(dòng)表查找函數(shù)??

{??

int?i?=?0;??

for?(i?=?0;?i?<?driversize;?i?++)??

????{??

if?((eventdriver[i].mod?==?mod)?&&?(eventdriver[i].event?==?event)?&&?(eventdriver[i].status?==?status))??

????????{??

return?eventdriver[i].eventfun;??

????????}??

????}??

return?NULL;??

}??

這種方法的好處:

1、提高了程序的可讀性拍嵌。一個(gè)消息如何處理遭赂,只要看一下驅(qū)動(dòng)表就知道,非常明顯横辆。

2撇他、減少了重復(fù)代碼。這種方法的代碼量肯定比第一種少狈蚤。為什么困肩?因?yàn)樗岩恍┲貜?fù)的東西:switch分支處理進(jìn)行了抽象,把其中公共的東西——根據(jù)三個(gè)元素查找處理方法抽象成了一個(gè)函數(shù)GetFunFromDriver外加一個(gè)驅(qū)動(dòng)表脆侮。

3锌畸、可擴(kuò)展性。注意這個(gè)函數(shù)指針靖避,他的定義其實(shí)就是一種契約潭枣,類似于java中的接口,c++中的純虛函數(shù)幻捏,只有滿足這個(gè)條件(入?yún)⑴枥纾祷刂担趴梢宰鳛橐粋€(gè)事件的處理函數(shù)篡九。這個(gè)有一點(diǎn)插件結(jié)構(gòu)的味道谐岁,你可以對(duì)這些插件進(jìn)行方便替換,新增瓮下,刪除翰铡,從而改變程序的行為。而這種改變讽坏,對(duì)事件處理函數(shù)的查找又是隔離的(也可以叫做隔離了變化)。例证、

4路呜、程序有一個(gè)明顯的主干。

5织咧、降低了復(fù)雜度胀葱。通過(guò)把程序邏輯的復(fù)雜度轉(zhuǎn)移到人類更容易處理的數(shù)據(jù)中來(lái),從而達(dá)到控制復(fù)雜度的目標(biāo)笙蒙。

繼承與組合

考慮一個(gè)事件驅(qū)動(dòng)的模塊抵屿,這個(gè)模塊管理很多個(gè)用戶,每個(gè)用戶需要處理很多的事件捅位。那么轧葛,我們建立的驅(qū)動(dòng)表就不是針對(duì)模塊了搂抒,而是針對(duì)用戶,應(yīng)該是用戶在某狀態(tài)下尿扯,收到某模塊的某事件的處理求晶。我們?cè)偌僭O(shè)用戶可以分為不同的級(jí)別,每個(gè)級(jí)別對(duì)上面的提到的處理又不盡相同衷笋。

用面向?qū)ο蟮乃悸贩夹樱覀兛梢钥紤]設(shè)計(jì)一個(gè)用戶的基類,實(shí)現(xiàn)相同事件的處理方法辟宗;根據(jù)級(jí)別不同爵赵,定義幾個(gè)不同的子類,繼承公共的處理泊脐,再分別實(shí)現(xiàn)不同的處理空幻。這是最常見(jiàn)的一種思路,可以叫它繼承法晨抡。

如果用表驅(qū)動(dòng)法怎么實(shí)現(xiàn)氛悬?直接設(shè)計(jì)一個(gè)用戶的類,沒(méi)有子類耘柱,也沒(méi)有具體的事件的處理方法如捅。它有一個(gè)成員,就是一個(gè)驅(qū)動(dòng)表调煎,它收到事件后镜遣,全部委托給這個(gè)驅(qū)動(dòng)表去進(jìn)行處理。針對(duì)用戶的級(jí)別不同士袄,可以定義多個(gè)不同的驅(qū)動(dòng)表來(lái)裝配不同的對(duì)象實(shí)例悲关。這個(gè)可以叫他組合法。

繼承和組合在《設(shè)計(jì)模式》也有提到娄柳。組合的優(yōu)勢(shì)在于它的可擴(kuò)展性寓辱,彈性,強(qiáng)調(diào)封裝性赤拒。(繼承和組合可以參考這篇文章:面向?qū)ο笾^承組合淺談

至于這種情況下的驅(qū)動(dòng)表秫筏,可以繼續(xù)使用結(jié)構(gòu)體,也可以使用對(duì)象挎挖。

上面的方法的一點(diǎn)性能優(yōu)化建議:

如果對(duì)性能要求不高这敬,上面的方法足可以應(yīng)付。如果性能要求很高蕉朵,可以進(jìn)行適當(dāng)?shù)膬?yōu)化崔涂。比如,可以建立一個(gè)多維數(shù)組始衅,每一維分別表示模塊冷蚂,狀態(tài)缭保,消息。這樣帝雇,就可以根據(jù)這三者的枚舉直接根據(jù)下標(biāo)定位到處理函數(shù)涮俄,而不是查表。(其實(shí)還是數(shù)據(jù)驅(qū)動(dòng)的思想:數(shù)據(jù)結(jié)構(gòu)是靜態(tài)的算法尸闸。)

數(shù)據(jù)驅(qū)動(dòng)編程再更高級(jí)彻亲,更為抽象一點(diǎn)的,應(yīng)該就是流程腳本或者DSL了吮廉。我曾經(jīng)寫過(guò)一個(gè)簡(jiǎn)單的寄生在xml上的腳本來(lái)描述流程苞尝。這一塊后面抽時(shí)間介紹。


參考鏈接:https://blog.csdn.net/chgaowei/article/details/6966857

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宦芦,一起剝皮案震驚了整個(gè)濱河市宙址,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌调卑,老刑警劉巖抡砂,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異恬涧,居然都是意外死亡注益,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門溯捆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丑搔,“玉大人,你說(shuō)我怎么就攤上這事提揍∑≡拢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵劳跃,是天一觀的道長(zhǎng)谎仲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)刨仑,這世上最難降的妖魔是什么强重? 我笑而不...
    開(kāi)封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮贸人,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘佃声。我一直安慰自己艺智,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布圾亏。 她就那樣靜靜地躺著十拣,像睡著了一般封拧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夭问,一...
    開(kāi)封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天泽西,我揣著相機(jī)與錄音,去河邊找鬼缰趋。 笑死捧杉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秘血。 我是一名探鬼主播味抖,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼灰粮!你這毒婦竟也來(lái)了仔涩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤粘舟,失蹤者是張志新(化名)和其女友劉穎熔脂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體柑肴,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霞揉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘉抒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片零聚。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖些侍,靈堂內(nèi)的尸體忽然破棺而出隶症,到底是詐尸還是另有隱情,我是刑警寧澤岗宣,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布蚂会,位于F島的核電站,受9級(jí)特大地震影響耗式,放射性物質(zhì)發(fā)生泄漏胁住。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一刊咳、第九天 我趴在偏房一處隱蔽的房頂上張望彪见。 院中可真熱鬧,春花似錦娱挨、人聲如沸余指。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)酵镜。三九已至碉碉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淮韭,已是汗流浹背垢粮。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留靠粪,地道東北人蜡吧。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像庇配,于是被迫代替她去往敵國(guó)和親斩跌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理捞慌,服務(wù)發(fā)現(xiàn)耀鸦,斷路器,智...
    卡卡羅2017閱讀 134,702評(píng)論 18 139
  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,835評(píng)論 0 38
  • 無(wú)聊小風(fēng)閱讀 200評(píng)論 0 0
  • 女人,有很多身份嗅虏,女兒洛姑,妻子,媳婦皮服,媽媽……各種身份集于一身時(shí)楞艾,瑣事纏身,往往被壓到生活的埃塵里龄广。委屈了自己硫眯,丟了...
    夏宇嫣_8335閱讀 309評(píng)論 1 0
  • 作者:余沁怡(來(lái)源:《福州大學(xué)報(bào)》) 四月,春暖花開(kāi)择同。遠(yuǎn)在南京的鄭姑娘的學(xué)辛饺耄花開(kāi)得燦爛,郁金香敲才、紫荊裹纳、櫻花、桃花紧武、...
    heyeyes閱讀 347評(píng)論 0 0