最近這個(gè)段時(shí)間都是忙于學(xué)習(xí) SpringFramework,那東東好樣的,只是剛剛學(xué)完Struts,Hibernate,有來(lái)了這個(gè),呵呵,,感覺(jué)挺累的。“你怎么把這兩個(gè)不相干的東西撤到一起?” ,確實(shí)是這樣! 無(wú)論從他們的設(shè)計(jì),實(shí)現(xiàn),使用等方面他們是風(fēng)馬牛不相及, 但本人認(rèn)為從理解的方面看他們有點(diǎn)類似。況且學(xué)習(xí)要從對(duì)比中學(xué)呀!這對(duì)初學(xué)者會(huì)有幫助于理解。
重要聲明:本人都是用自己的語(yǔ)言寫的,有專業(yè)術(shù)語(yǔ)不對(duì)還請(qǐng)大家指出。: - )
就說(shuō)設(shè)計(jì)模式 Decorator,也就是裝飾模式,這還不好理解?在原有的東西上進(jìn)行裝飾一下便是裝飾了。既然是裝飾,你要有主體呀(被修飾的東西),還要有裝飾品。但是不管你裝飾來(lái)裝飾去,他的本質(zhì)是不變的。就象人帶上了面具,但他還是人。墻上打上了油漆,但它還是墻呀。你也許覺(jué)得這是廢話。 但理解這點(diǎn)很重要(這是跟策略模式Strategy的區(qū)別),本人覺(jué)得這個(gè)是理解好 Decorator模式很重要的一點(diǎn)。在開發(fā)中你經(jīng)常要增強(qiáng)一個(gè)類的功能,或者是撤銷一個(gè)類的某些功能,但是一個(gè)類給眾多的功能進(jìn)行裝飾了以后,也許原來(lái)的類已經(jīng)面目全非了,你往往會(huì)感到茫然,其實(shí),你主要抓住他的主體,腦子里面時(shí)刻要知道你現(xiàn)在所作的工作就是為這個(gè)主體進(jìn)行打扮的工作。
研究過(guò)Jive的都知道, 里面的 Filter 就是用了Decorator 設(shè)計(jì)模式,那么在這個(gè)設(shè)計(jì)里面,它的主體是什么? ForumMessage ,無(wú)疑是 ForumMessage 。裝飾品當(dāng)然是Filter 了,所以我們?cè)谧鬟@件事情的時(shí)候始終是以ForumMessage為核心的,F(xiàn)ilter 進(jìn)行裝飾的時(shí)候,你千萬(wàn)不要忘記你現(xiàn)在是為ForumMessage而工作!有關(guān)于jive研究的文章,網(wǎng)上一大堆,現(xiàn)在看看一個(gè)比較簡(jiǎn)單的 Decorator:
//比如有一個(gè)抽象構(gòu)件:
public interface Component {
void operation();
}
//一個(gè)具體構(gòu)件:
public class ConcreteComponent implements Component {
public void operation() {
//Write your code here
}
}
//一個(gè)抽象裝飾:
public class Decorator implements Component {
private Component component; //引用
… …. …. …
//商業(yè)方法,委派給構(gòu)件
public void operation() {
component.operation();
}
}
//一個(gè)具體裝飾:
public class ConcreteDecorator extends Decorator {
/**
* 商業(yè)方法
*/
public void operation(){
//一些具體的裝飾的代碼
......
super.operation(); // 主體
//一些具體的裝飾的代碼
.......
}
}
...... |
我們主要看看,在ConcreteDecorator 中的operation()方法,他的父類是委托到component組建來(lái)完成的,其實(shí)它就是主體,一些裝飾代碼都會(huì)在這個(gè)方法(主體)執(zhí)行前進(jìn)行“預(yù)處理”或是執(zhí)行后進(jìn)行“收尾”。
可不是,從上面很容易就看出了,抽象裝飾中的operation()方法沒(méi)有在具體的裝飾類中進(jìn)行“全盤”覆蓋,因?yàn)樗昧藄uper.operation(); 這樣的語(yǔ)句??梢?jiàn)裝飾模式中不管怎么樣,你都要找到類似這個(gè)的方法。說(shuō)明他的主體還在。(這是跟策略模式Strategy的區(qū)別)
說(shuō)了這么多,不知道大家有沒(méi)有感覺(jué)到ConcreteDecorator類中的operation()方法跟Spring AOP 中的 InvocationHandler 接口的invoke()方法有點(diǎn)相類是呢?
我們來(lái)看看要實(shí)現(xiàn) InvocationHandler 時(shí)候要重寫的invoke()方法:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
…………………….
result = method.invoke(originalObject, args);
……………………………..
return result;
} |
InvocationHandler.invoke 方法將在被代理類的方法被調(diào)用之前觸發(fā)。通過(guò)這個(gè)方法中,我們可以在被代理類方法調(diào)用的前后進(jìn)行一些處理,如上面代碼中所示,InvocationHandler.invoke方法的參數(shù)中傳遞了當(dāng)前被調(diào)用的方法(Method),以及被調(diào)用方法的參數(shù)。同時(shí),我們可以通過(guò)Method.invoke方法調(diào)用被代理類的原始方法實(shí)現(xiàn)。這樣,我們就可以在被代理類的方法調(diào)用前后大做文章。(說(shuō)明:引用了Spring 開發(fā)指南中的一段)
在回到裝飾模式,其方法operation() 在執(zhí)行前和執(zhí)行后,也可以對(duì)它大做文章。如此看來(lái), Spring AOP 和 Decorator,從理解層面上來(lái)看,確實(shí)有點(diǎn)相象,注意:只是理解層面, 而他們的實(shí)現(xiàn)完全兩馬事!
其實(shí)主要是大家怎么看待這個(gè)問(wèn)題,按照本人的理解,Spring AOP 也可以說(shuō)是一種廣義的裝飾,但它又不是裝飾模式。它同樣也是對(duì)某個(gè)方法加上了限制,比如insert() 的時(shí)候,你要對(duì)它做執(zhí)行前開啟事務(wù)和執(zhí)行后提交或回滾這樣的“裝飾”。 又比如你也可以對(duì)某個(gè)人操作資源后做log這樣的裝飾工作等等。他們的相同之處就這么點(diǎn)。
AOP 也不是什么新的東西,當(dāng)然如果你的AOP是容器(Jboss 4.0)實(shí)現(xiàn)的話, 那么按照上面說(shuō)的,你的一些方法就會(huì)被容器所“裝飾”。
如此看來(lái),更多的時(shí)候可以理解為 Spring AOP 和一些AOP 容器是在系統(tǒng)級(jí)的,容器級(jí)的“裝飾”。 而裝飾模式則是業(yè)務(wù)級(jí)的裝飾。 這點(diǎn)其實(shí)從客戶端也很容易理解。
如果是AOP ,程序員可以放心的寫你的代碼(即使有點(diǎn)笨也不怕,有AOP護(hù)著呢)。 因?yàn)橄到y(tǒng)將在系統(tǒng)運(yùn)行時(shí)候?qū)@段代碼進(jìn)行“裝飾”。也就是說(shuō),這些裝飾不會(huì)出現(xiàn)在客戶端的代碼中,而Decorator模式呢?呵呵,這個(gè)時(shí)候程序員要有點(diǎn)頭腦了,他們要自己組裝一些裝飾類,按照某一種機(jī)制對(duì)主體進(jìn)行裝飾。也就是說(shuō),這些修飾類要出現(xiàn)在客戶端的代碼中。看代碼就知道了 :--)
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(input);
....//主體是System.in |