| 在Delphi中應(yīng)用AOP實(shí)現(xiàn)日志功能AOP現(xiàn)在很火,網(wǎng)上有這許多支持AOP的框架,對(duì)于Delphi來(lái)說(shuō)同樣也有MeAOP。不過(guò)覺(jué)得這些框架太復(fù)雜了。 AOP現(xiàn)在很火,網(wǎng)上有這許多支持AOP的框架,對(duì)于delphi來(lái)說(shuō)同樣也有MeAOP。不過(guò)覺(jué)得這些框架太復(fù)雜了。 現(xiàn)在有一個(gè)系統(tǒng),基本上都快結(jié)束了,整體上當(dāng)然是沒(méi)有采用什么AOP的框架。對(duì)于這樣的系統(tǒng)能否用上AOP的一點(diǎn)點(diǎn)好處呢? 項(xiàng)目組提出在現(xiàn)有的系統(tǒng)上加入日志記錄的需求。大家一起來(lái)看看我是怎么來(lái)實(shí)現(xiàn)這個(gè)功能的吧。 AOP簡(jiǎn)要說(shuō)明 根據(jù)網(wǎng)上對(duì)AOP的解釋?zhuān)哂邢旅娴奶卣鳎?BR> 1、將通用功能從不相關(guān)類(lèi)之中分離出來(lái); 2、能夠使得很多類(lèi)共享一個(gè)功能,一旦功能發(fā)生變化,不必修改很多類(lèi),只要修改這個(gè)功能就可以了。 AOP的核心在于保持橫切關(guān)注點(diǎn)的分離。 日志功能 這是一個(gè)比較典型的MIS系統(tǒng),現(xiàn)在編碼基本結(jié)束。不過(guò)某個(gè)開(kāi)發(fā)人員接到了一個(gè)繁瑣又看上去沒(méi)什么技術(shù)含量的任務(wù)——實(shí)現(xiàn)日志功能。這個(gè)開(kāi)發(fā)者就是本人了。 雖然沒(méi)什么難度,但還是設(shè)計(jì)一下吧,誰(shuí)讓我是一個(gè)自詡為高水平的程序員呢。 一個(gè)設(shè)計(jì)圖就這么做出來(lái)了。其中設(shè)計(jì)一個(gè)接口ILog來(lái)封裝日志實(shí)現(xiàn)的細(xì)節(jié)。模塊甲乙丙只需要使用接口ILog就可以。滿(mǎn)足了XXX面向?qū)ο蟮脑O(shè)計(jì)原則。太完美了! 泡杯茶,然后開(kāi)始寫(xiě)代碼實(shí)現(xiàn)這個(gè)簡(jiǎn)單而龐大的任務(wù)。 開(kāi)始編碼了! TLog,ILog實(shí)現(xiàn)比較簡(jiǎn)單,在此略去不談。稍微修改一下以前模塊的代碼,將ILog接口傳入每一個(gè)模塊中。 接下來(lái)只需要實(shí)現(xiàn)日志功能的調(diào)用就可以了。 模塊甲: 
 模塊乙: 
 就這樣,寫(xiě)了大約二十幾個(gè)地方,突然覺(jué)得自己太可悲了,作為一個(gè)高科技人才就干這種體力活嗎? 壞味道的出現(xiàn) 在許許多多的地方都出現(xiàn)了Flog.LogCommand這樣的函數(shù)調(diào)用,正是這些函數(shù)調(diào)用讓我崩潰,在這么做下去估計(jì)我撐不到周末了。 “CV大法”已經(jīng)讓我覺(jué)得羞愧加惱怒,系統(tǒng)中到處出現(xiàn)了這樣的重復(fù)代碼。 無(wú)奈之中,我耷拉著腦袋走到一個(gè)同事桌前。 “嘿,救救我吧,我想解脫” “怎么回事?”同事善意地問(wèn)道。 “事情是這樣子的……” 通過(guò)了一番討論,我們一致認(rèn)為這個(gè)應(yīng)該用AOP的思想來(lái)解決。但怎樣在delphi中來(lái)實(shí)現(xiàn)AOP呢,修改整個(gè)程序框架是不可能的,我們只能在現(xiàn)有的基礎(chǔ)上做。 正當(dāng)我們要放棄的時(shí)候,突然想到了一個(gè)突破點(diǎn):日志中記錄的功能在程序?qū)崿F(xiàn)的時(shí)候全部使用Action組件來(lái)做的,是否可以考慮在Action上面做文章呢? 曙光啊,曙光! 解決方式——瞞天過(guò)海 通俗點(diǎn)理解AOP,就是將一段代碼統(tǒng)一“插入”某一類(lèi)地方。但像delphi這樣的語(yǔ)言是很難實(shí)現(xiàn)“插入”代碼的這一功能。不過(guò)我們可以通過(guò)事件機(jī)制來(lái)實(shí)現(xiàn)同樣的效果。 Action的執(zhí)行代碼都寫(xiě)在事件OnExecute中,如果能在執(zhí)行事件之前和之后執(zhí)行我想要的動(dòng)作是不是就可以解決了? 
 相關(guān)的UML圖如下: 
 采用這樣的方式后,很明顯我們不需要將日志相關(guān)代碼分散到系統(tǒng)的各個(gè)地方,只需要在一個(gè)統(tǒng)一的地方將所有Form上的Action組件注冊(cè)到TActionHook中就可以了。 擴(kuò)展思考 在delphi中可以通過(guò)事件的機(jī)制實(shí)現(xiàn)代碼注入技術(shù),當(dāng)然同樣在其他支持事件的語(yǔ)言中也可以實(shí)現(xiàn)。相比之下這種方法實(shí)現(xiàn)AOP比較簡(jiǎn)單,并且不需要在系統(tǒng)的整體結(jié)構(gòu)上作什么調(diào)整,完全通過(guò)語(yǔ)言層面支持。 例子中針對(duì)Action的組件來(lái)處理日志功能,將TActionHook擴(kuò)展之后可以將其他的控件操作也通過(guò)這套機(jī)制記錄到日志中。 很多同行們都埋怨自己做的是體力活,沒(méi)什么技術(shù)含量。同樣在剛開(kāi)始的時(shí)候,我也認(rèn)為這個(gè)任務(wù)是體力活,但是如果我們能勤于思考新的解決方法,體力活絕對(duì)能夠變?yōu)榧夹g(shù)活。只有這樣才能不辜負(fù)“高科技”這個(gè)美譽(yù)啊。 上面介紹的方法肯定不是最好的,這次拿出來(lái)和大家分享,一方面是將自己的經(jīng)驗(yàn)獻(xiàn)給需要的朋友,另外也特別希望大家能給一點(diǎn)好的建議,一起交流,共同學(xué)習(xí)。 | 
|  | 
來(lái)自: 獨(dú)孤求財(cái) > 《DELPHI》