"高內(nèi)聚、低耦合"
? ? 大家在談到面向?qū)ο?a target="_blank">編程的時(shí)候基本都是討論軟件的“高內(nèi)聚、低耦合”的特點(diǎn),這6個(gè)字也是算是成為了大部分評(píng)判代碼質(zhì)量的一個(gè)標(biāo)準(zhǔn),所以很多小伙伴一開(kāi)始學(xué)習(xí)編程就會(huì)問(wèn)道:"如何實(shí)現(xiàn)代碼的高內(nèi)聚、低耦合"?我只想說(shuō)這個(gè)問(wèn)題還真不是三言兩句就能說(shuō)清楚的,需要開(kāi)發(fā)人員有一定的代碼量和軟件設(shè)計(jì)方面的開(kāi)發(fā)實(shí)戰(zhàn)經(jīng)驗(yàn)。
? ? 不過(guò)既然提到了,作者就在這里談?wù)勛约旱囊恍┱J(rèn)知和看法,在討論一些問(wèn)題的時(shí)候首先我們需要有設(shè)置一定的前提條件,否則一味的談?wù)撌菦](méi)有絲毫意義的,所以在分析前我們需要確定一個(gè)維度來(lái)看待問(wèn)題,高內(nèi)聚需要內(nèi)部代碼和功能形成較強(qiáng)的關(guān)聯(lián),而低耦合卻是要降低模塊間的內(nèi)部依賴。
? ? 打個(gè)比方: 從人類角度看,每個(gè)人類都是一個(gè)單一的個(gè)體,其眼睛、鼻子、嘴巴等等形成了一個(gè)高度的內(nèi)聚。而人與人之間又相互獨(dú)立,形成了一個(gè)較低的耦合。然而我們?nèi)绻麚Q一個(gè)角度來(lái)看來(lái)人類,那么人與人之間或許又形成了一個(gè)較強(qiáng)的內(nèi)聚,人與其他動(dòng)物之間又形成了較低的耦合,所以進(jìn)一步類比代碼設(shè)計(jì)也就是一樣的道理了,面向?qū)ο笃鋵?shí)也就為了實(shí)現(xiàn)這個(gè)目標(biāo)而產(chǎn)生的,所以這里我們用萬(wàn)能C來(lái)看看如何引入該思想:
3、用面向?qū)ο髞?lái)玩C編程
? ? C面向?qū)ο缶幊讨庋b
? ?對(duì)于封裝性,看過(guò)我的一些文章小伙伴應(yīng)該有一個(gè)比較清晰的認(rèn)識(shí)了吧,特別是講解結(jié)構(gòu)體的時(shí)候,其中有個(gè)非常精妙的圖不知道大家還是否記得,如果不記得可以進(jìn)去先看看,<【典藏】大佬們都在用的結(jié)構(gòu)體進(jìn)階小技巧>,結(jié)構(gòu)體就是數(shù)據(jù)的集合,數(shù)據(jù)就是一個(gè)對(duì)象的屬性和方法,把共用的接口給外部使用,把私用的進(jìn)行隱蔽,這樣就形成了良好的封裝,下面直接上最簡(jiǎn)單的理解代碼:
示例代碼:
?
1#include?2#include? 3/************************************** 4?*?Fuction:?仿類? 5?* Author :(公眾號(hào):最后一個(gè)bug)? 6?**************************************/ 7typedef?struct?_tag_Class 8{ 9????int?Val; 10????void?(*pmethod)(struct?_tag_Class*?pData); 11}sClass; 12 13/************************************** 14?*?Fuction:?方法? 15?* Author :(公眾號(hào):最后一個(gè)bug)? 16?**************************************/ 17void?printfVal(sClass*?pObject) 18{ 19 20????printf("Object:%d ",pObject->Val); 21} 22/************************************** 23?*?Fuction:?main 24?* Author :(公眾號(hào):最后一個(gè)bug)? 25?**************************************/ 26int?main(int?argc,?char?*argv[])?{ 27????//定義兩個(gè)對(duì)象? 28????sClass?stObject1; 29????sClass?stObject2; 30????//初始化對(duì)象屬性? 31????stObject1.Val?=?1; 32????stObject2.Val?=?2;? 33????stObject1.pmethod?=?printfVal; 34????stObject2.pmethod?=?printfVal; 35????//進(jìn)行對(duì)象的使用? 36????stObject1.pmethod(&stObject1); 37????stObject2.pmethod(&stObject2); 38 39????printf("歡迎關(guān)注公眾號(hào):最后一個(gè)bug "); 40????return?0; 41}
?
運(yùn)行結(jié)果:
? ? C面向?qū)ο缶幊讨^承
? ?對(duì)于繼承性,就是父母有的我都有,并且還會(huì)有自己獨(dú)特的地方(數(shù)據(jù)),對(duì)于代碼里面無(wú)非就是屬性和方法了,結(jié)合結(jié)構(gòu)體地址總是指向其結(jié)構(gòu)體首地址的特點(diǎn),利用父子結(jié)構(gòu)體前面字段相同進(jìn)行直接地址傳遞以后強(qiáng)制類型轉(zhuǎn)化便可以進(jìn)行訪問(wèn),不過(guò)這僅僅只是單繼承,對(duì)于多繼承問(wèn)題作者暫時(shí)不展開(kāi)。
示例代碼:
?
1#include?2#include? 3?/************************************** 4??*?Fuction:?仿父類? 5??* Author :(公眾號(hào):最后一個(gè)bug)? 6??**************************************/ 7?typedef?struct?_tag_Parent 8?{ 9????int?ParentVal;?//父類屬性? 10???void?(*pmethod)(struct?_tag_Parent*?pData);//父類方法? 11}sParent; 12 13/************************************** 14?*?Fuction:?仿子類? 15?* Author :(公眾號(hào):最后一個(gè)bug)? 16**************************************/ 17typedef?struct?_tag_Child 18{ 19????sParent?ParentObj;//繼承父類數(shù)據(jù)和方法? 20????int?ChildVal;//子類特殊屬性? 21???void?(*pmethod)(struct?_tag_Child*?pData);//子類特殊方法? 22}sChild; 23 24/************************************** 25?*?Fuction:?父類方法? 26?* Author :(公眾號(hào):最后一個(gè)bug)? 27?**************************************/ 28void?ParentprintfVal(sParent*?pObject) 29{ 30 31????printf("Parent?Object:%d ",pObject->ParentVal); 32} 33 34/************************************** 35?*?Fuction:?子類方法? 36?* Author :(公眾號(hào):最后一個(gè)bug)? 37?**************************************/ 38void?ChildprintfVal(sChild*?pObject) 39{ 40 41????printf("Child?Object:%d ",pObject->ChildVal); 42} 43 44/************************************** 45?*?Fuction:?對(duì)接父類的公共接口? 46?* Author :(公眾號(hào):最后一個(gè)bug)? 47?**************************************/ 48void?printfVal(sParent*?pObject) 49{ 50????pObject->pmethod(pObject); 51} 52 53/************************************** 54?*?Fuction:?main 55?* Author :(公眾號(hào):最后一個(gè)bug)? 56?**************************************/ 57int?main(int?argc,?char?*argv[])?{ 58????//定義父類對(duì)象? 59????sParent?stParentObj; 60????sChild??stChildObj; 61 62????//構(gòu)造(初始化對(duì)象和方法)? 63????stParentObj.ParentVal?=?10; 64????stParentObj.pmethod???=?ParentprintfVal; 65 66????//初始化子類對(duì)象和方法? 67????stChildObj.ParentObj.ParentVal??=?20; 68????stChildObj.ParentObj.pmethod????=?ParentprintfVal; 69????stChildObj.ChildVal?????????????=?11; 70????stChildObj.pmethod??????????????=?ChildprintfVal; 71 72????//調(diào)用公共的外部接口? 73????printfVal((sParent*)&stParentObj); 74????printfVal((sParent*)&stChildObj); 75 76????printf("歡迎關(guān)注公眾號(hào):最后一個(gè)bug "); 77????return?0; 78}
?
運(yùn)行結(jié)果:
? ? C面向?qū)ο缶幊讨鄳B(tài)
? ??多態(tài)簡(jiǎn)單一點(diǎn)說(shuō)就是一個(gè)接口可以產(chǎn)生多種狀態(tài)處理,上一節(jié)其實(shí)也說(shuō)明了這個(gè)特性,不過(guò)C++中的多態(tài)來(lái)自編譯的多態(tài)和運(yùn)行時(shí)的多態(tài),比如重載包括類重載和函數(shù)重載屬于編譯多態(tài)、虛函數(shù)等等屬于運(yùn)行時(shí)多態(tài),如果完全用C來(lái)模擬其實(shí)現(xiàn)還是相對(duì)比較復(fù)雜的,不過(guò)我們的目的僅僅只是說(shuō)引入面向?qū)ο蟮囊恍┧悸穪?lái)指導(dǎo)C編程,這里對(duì)于C編程就簡(jiǎn)單一點(diǎn)實(shí)現(xiàn)函數(shù)重載,在C中通過(guò)傳遞參數(shù)就能夠?qū)崿F(xiàn)一個(gè)函數(shù)的多態(tài),不過(guò)這個(gè)傳參可能需要更加靈活一點(diǎn),上代碼:
示例代碼:
?
1#include?2#include? 3/************************************** 4?*?Fuction:?任意數(shù)據(jù)結(jié)構(gòu)? 5?* Author :(公眾號(hào):最后一個(gè)bug)? 6?**************************************/ 7typedef?struct?_tag_Data 8{ 9????void*?pdata; 10????void?(*method)(struct?_tag_Data*?pData); 11}sData; 12 13/************************************** 14?*?Fuction:?具體實(shí)現(xiàn)1? 15?* Author :(公眾號(hào):最后一個(gè)bug)? 16?**************************************/ 17void?Add(sData?*pData)? 18{ 19????int?*?Data?=?(int?*)pData->pdata; 20????printf("Add?=?%d ",(Data[0]?+?Data[1])); 21} 22 23/************************************** 24?*?Fuction:?具體實(shí)現(xiàn)2 25?* Author :(公眾號(hào):最后一個(gè)bug)? 26?**************************************/ 27void?Sub(sData?*pData)? 28{ 29????int?*?Data?=?(int?*)pData->pdata; 30 31????printf("Sub?=?%d ",(Data[0]?-?Data[1])); 32} 33 34/************************************** 35?*?Fuction:?多態(tài)函數(shù)? 36?* Author :(公眾號(hào):最后一個(gè)bug)? 37?**************************************/ 38void??Cal(sData?*pData)? 39{ 40??pData->method(pData); 41} 42 43/************************************** 44?*?Fuction:?main 45?* Author :(公眾號(hào):最后一個(gè)bug)? 46?**************************************/ 47int?main(int?argc,?char?*argv[])?{ 48 49????int?Array[2]?={4?,2}; 50????sData?stData1; 51????sData?stData2; 52 53????stData1.pdata??=?(void*)Array; 54????stData1.method?=?Add; 55 56????stData2.pdata??=?(void*)Array; 57????stData2.method?=?Sub; 58 59?????Cal(&stData1); 60?????Cal(&stData2); 61 62????printf("歡迎關(guān)注公眾號(hào):最后一個(gè)bug "); 63????return?0; 64}
?
運(yùn)行結(jié)果:
4、最后小結(jié)
? ? 今天用C引出面向?qū)ο缶椭v這么多吧,因?yàn)楹芏嘈』锇闆](méi)有系統(tǒng)學(xué)習(xí)過(guò)C++語(yǔ)言,可能對(duì)于面向?qū)ο蟮睦斫獠皇翘貏e形象,所以作者上面也只是簡(jiǎn)單的是C模擬了面向?qū)ο缶幊痰摹氨弦唤?,更多實(shí)現(xiàn)作者還會(huì)在后期的文章進(jìn)行闡述,這里就簡(jiǎn)單給大家嘗個(gè)鮮。
????目前也存在非常多新型的編程設(shè)計(jì)模式,最終的編程我們還是要落在解決具體的問(wèn)題、滿足用戶需求上來(lái),就像一個(gè)簡(jiǎn)單的設(shè)計(jì)其實(shí)根本就不需要有太多高級(jí)編程技巧的。然而對(duì)于嵌入式應(yīng)用方面大部分的軟件設(shè)計(jì)還并沒(méi)有發(fā)展到面向?qū)ο笏悸窡o(wú)法勝任的地步?! ?/p>
?
評(píng)論
查看更多