|
然后在程序里面你調用了大量的AFunction,但是有一天,你突然發現你要用BFunction了,(不過AFunction又不能不要,很有可能你以后還要調用),這個時候,你就可以#define MacroFunction Bfunction來達到這樣的目的。
2.靜態的入口函數,保證函數名相同,利用標志位調用子函數:
這樣的典型應用很多,比如說網卡驅動里面有一個入口函數Nilan(int FunctionCode,Para*)。具體的參數是什么記不清楚了。不過NiLan的主體是這樣的:
|
寫到這里大家明白什么意思了吧。保證相同的函數名就是說:網卡驅動是和pNA+協議?;ミB的,那么如何保證pNA+協議棧和不同的驅動都兼容呢,一個簡單的辦法就是僅僅使用一個入口函數。通過改變如果函數的參數值,來調用內部的各個函數。
這樣的做法是可以進化的:如果以后想調用新的函數,增加相應的函數參數值就好了。如果我們將網卡驅動和pNA+協議??醋鲀蓚€層的話,我們可以發現:層與層之間的互連接口是很小的(這里是一個入口函數),一般是采用名字解析的辦法而不是具體的函數調用(利用FunctionCode調用函數,Nilan僅僅實現名字解析的功能)――!接口限制和名字解析
接口限制:層與層之間僅僅知道有限的函數
名字解析:層與層之間建立共同的名字與函數的對應關系,之間利用名字調用功能。
3.CALLBACK函數
我覺得這是C語言的一個創舉,雖然它很簡單,就象如何把雞蛋豎起來一樣,但是你如果沒想到的話,仍然是一個難題。如果說靜態入口函數實現了一個可管理的宏觀的話,CallBack就是實現了一個可進化的微觀:它使得一個函數可以在不重新編譯的情況下實現功能的添加!但是在最最早期的時候,也有蠻多人持反對態度,因為它用了函數指針。
函數指針雖然靈活,但是由于它要訪問內存兩次才可以調用到函數,第一次訪問函數指針,第二次才是真正的函數調用。它的效率是不如普通函數的。但是在一個不太苛刻的環境下,函數調用本身就不怎么耗時,函數指針的性能又不是特別糟糕,使用函數指針其實是一個最好的選擇。
但是函數指針除了性能,最麻煩的地方就是會導致程序的“支離破碎”。試想:在程序中,你讀到一個函數指針的時候,如果你愣是不知道這個函數指針指向的是哪個函數,那個感覺真的很糟糕。(可以看后面的文章,要使用先進的程序框架,避免這樣的情況)
三、Event和Message
看了上面的描述,相信大家多少有些明白為什么要使用Event和Message了。具體的函數調用會帶來很多的問題(雖然從效率上講,這樣做是很好的)。為了提高程序的靈活性,Event和Message的辦法產生了。用名字解析的辦法代替通常的函數調用,這樣,如果雙方對這樣的解析是一致的話,就可以達到一個統一。不過Event和Message的作用還不僅僅是如此。
Event和Message還有建立進程間通信的功能。進程將自己的消息發給“控制中心”(簡單的就是一個消息隊列,和一個while循環不斷的取消息隊列的內容并執行),控制程序得到消息,分發給相應的進程,這樣其他進程就可以得到這個消息并進行響應。
Event和Message是很靈活的,因為你可以隨時添加或者關閉一個進程,(僅僅需要添加分發消息的列表就可以了)Event和Message從程序實現上將我覺得是一樣的,只不過概念不同。Event多用于指一個動作,比如硬件發生了什么事情,需要調用一個什么函數等等。Message多用于指一個指示,比如什么程序發生了什么操作命令等等。
四、小結
其實編程序和寫文章一樣,都是先有一個提綱,然后慢慢的豐富。先抽象化得到程序的骨架,然后再考慮各個方面的其他內容:比如說程序極端的時候會發生什么問題?程序的這個地方的功能現在還不完善,以后再完善會有什么問題?程序是不是可以擴展的?
原文轉自:http://www.anti-gravitydesign.com