新聞中心
簡介

創(chuàng)新互聯(lián)建站成都企業(yè)網(wǎng)站建設(shè)服務(wù),提供成都網(wǎng)站建設(shè)、網(wǎng)站制作網(wǎng)站開發(fā),網(wǎng)站定制,建網(wǎng)站,網(wǎng)站搭建,網(wǎng)站設(shè)計,成都響應(yīng)式網(wǎng)站建設(shè),網(wǎng)頁設(shè)計師打造企業(yè)風(fēng)格網(wǎng)站,提供周到的售前咨詢和貼心的售后服務(wù)。歡迎咨詢做網(wǎng)站需要多少錢:18980820575
Servlet規(guī)范中所引入的filter令人心動不已,因為它引入了一個功能強大的攔截模式。Filter是這樣一種Java對象,它能在request到達servlet的服務(wù)方法之前攔截Http Servlet Request對象,而在服務(wù)方法轉(zhuǎn)移控制后又能攔截HttpServletResponse對象。你可以使用filter來實現(xiàn)特定的任務(wù),比如驗證用戶輸入,以及壓縮web內(nèi)容。但你擬富有成效地使用過濾器的念頭卻被你不能改變Http Servlet Request對象的參數(shù)的現(xiàn)實掃了興,因為java.util.Map所包裝的Http Servlet Request對象的參數(shù)是不可改變的。這極大地縮減了filter的應(yīng)用范圍。至少在一半的時間里,你希望可以改變準(zhǔn)備傳送給filter的對象。如果在Http Servlet Request對象到達Struts的action servlet之前,我們可以通過一個filter將用戶輸入的多余空格去掉,難道不是更美妙嗎?這樣的話,你就不必等到在Struts的action表單驗證方法中才進行這項工作了。
幸運的是,盡管你不能改變不變對象本身,但你卻可以通過使用裝飾模式來改變其狀態(tài)。
裝飾模式
在繼承中,你可以通過繼承一個父類并覆蓋你希望改變的方法來改變對象狀態(tài)。然而,如果這個對象是由程序的另一個子模塊,例如對象工廠 (這里所說的工廠是工廠模式中的術(shù)語,下同。譯者注) 或是servlet容器所產(chǎn)生的,繼承就無能為力了。
裝飾模式可用來增加一個現(xiàn)有對象的功能,或是改變其狀態(tài)。與其使用繼承方式來擴展此類,這個模式將一個對象包裝成另外一個對象。裝飾模式的UML類圖。
裝飾模式
Component是一個接口,其具體實現(xiàn)是ConcreteComponent。要改變Component的狀態(tài),你可以修改 ConcreteComponent或是擴展它 (通過繼承或?qū)崿F(xiàn)接口的方式,譯者注)。然而,如果ConcreteComponent來自于一個工廠,你卻無計可施。你所能做的,就是創(chuàng)建一個同為實現(xiàn)了Component接口的裝飾類。這個裝飾類的角色就由Decorator來扮演,在程序中通常表現(xiàn)為接口或抽象類。Decorator類的一個特性就是,它有一個接收Component對象的構(gòu)造方法。你將擬裝飾的對象傳遞給這個構(gòu)造方法。在本例中,這個對象就是從工廠獲得的 ConcreteComponent對象。通過將此裝飾對象傳遞給Decorator的一個類變量,你可以訪問Decorator中的任何方法。這就使你得以改變對象的狀態(tài)了。
Decorator類不一定是接口或抽象類。如果你的程序不是很復(fù)雜,你可以將其轉(zhuǎn)化為一個具體的Decorator類。
舉個例子,考慮這樣一個簡單的消息傳遞程序,其主要部分是Messenger接口及其實現(xiàn)類MessengerImpl。讓我們假設(shè) MessengerImpl對象來自于一個工廠,因此你不能改變其狀態(tài)。如果你準(zhǔn)備增加或改變Messenger對象的功能,你可以創(chuàng)建一個 MessengerDecorator類。此例子的類圖。
Messenger裝飾類
我們來看程序的代碼。給出了Messenger接口的代碼,MessengerImpl類的代碼。
Messenger接口
- public interface Messenger {
- public String getMessage()
- }
MessengerImpl類
- public class MessengerImpl
- implements Messenger {
- private String message
- public MessengerImpl(String message) {
- this.message = message
- }
- public String getMessage() {
- return message
- }
- }
Messenger對象由一個名為MessengerFactory的工廠創(chuàng)建。
MessengerFactory類
- public class MessengerFactory {
- public static Messenger getMessenger()
- {
- return new MessengerImpl("secrets")
- }
- }
對每一個所創(chuàng)建的Messenger對象,此工廠通過某個未知的操作,初始化了getMessage()方法所返回的字符串。換句話說,你不能自己創(chuàng)建Messenger對象。
在程序中,Messenger對象的主要用途是被傳遞給一個名為Util的類中的broadcast()靜態(tài)方法。
Util類
- public class Util {
- public static void broadcast(Messenger messenger) {
- System.out.print(messenger.getMessage());
- }
- // other methods here
- }
在你自己的類中,你可能會有這樣的代碼:
- Messenger messenger = MessengerFactory.getMessenger();
- Util.broadcast(messenger);
假設(shè)你希望對broadcast()方法所打印出的消息做一小改動。你擬將其轉(zhuǎn)為大寫,怎么做?表面上看,你可以繼承Messenger,實例化其子類,并將返回的對象傳給Util.broadcast()。但是,這種做法毫無意義,因為只有工廠才知道如何初始化Messenger對象,并通過其 getMessage()方法返回正確的值。
使用裝飾模式,你可以創(chuàng)建一個MessengerDecorator類。
MessengerDecorator類
- public class MessengerDecorator implements Messenger {
- private Messenger messenger;
- public MessengerDecorator(Messenger messenger) {
- this.messenger = messenger;
- }
- public String getMessage() {
- return messenger.getMessage().toUpperCase();
- }
- }
因為MessengerDecorator實現(xiàn)了Messenger,Util.broadcast()將接受一個MessengerDecorator 的實例。然而,MessengerDecorator不僅僅是一個接口的實現(xiàn),它還是一個MessengerImpl對象的裝飾器。正因如此,MessengerDecorator就必須有一個接收擬被裝飾的Messenger對象的構(gòu)造方法。
這個構(gòu)造方法將參數(shù)傳給變量。你現(xiàn)在可以覆蓋MessengerDecorator中的getMessage()方法,以便將消息轉(zhuǎn)為大寫后再打印出來。因為你持有原來Messenger對象的引用,你可以這樣寫getMessage()方法:
- public String getMessage() {
- return this.messenger.getMessage().toUpperCase()
- }
MessengerDecorator中的getMessage()方法返回原始消息的大寫版本。
在你的類中,就像往常一樣,你得到一個Messenger對象,并將Decorator傳給Util.broadcast()。
Messenger messenger = factory.getMessenger();
Util.broadcast(new MessengerDecorator(messenger));
你并不將原始對象傳給原先的目標(biāo),相反,你將其傳給了該對象的裝飾器。
應(yīng)用裝飾模式于Servlet
以上Messenger類的例子與servlet容器所構(gòu)造的ServletRequest對象是一樣的。當(dāng)收到一個HTTP請求時,servlet容器就會創(chuàng)建ServletRequest對象及ServletResponse對象(分別是ServletRequestImpl及ServletResponseImpl的實例),并將這兩個對象傳遞給特定的servlet服務(wù)方法。現(xiàn)在,如果你為ServletRequest創(chuàng)建一個裝飾角色,并將其傳給servlet服務(wù)方法,你就應(yīng)用了裝飾模式。
對ServletRequest很容易應(yīng)用裝飾模式,因為servlet API已經(jīng)為其提供了一個包裝類:ServletRequestWrapper。servlet裝飾模式的類圖。
Servlet API中的裝飾模式
別為過多的類搞暈了頭,只管注意虛線框中的三個類就行了:Http Servlet Request, Http Servlet RequestImpl, Http Servlet RequestWrapper。
Servlet API (HTTP)的裝飾模式
情況與前面所舉例子類似。你擁有一個ServletRequest的實現(xiàn),而它是由servlet容器產(chǎn)生的。你可以使用所提供的ServletRequestWrapper來裝飾這些ServletRequest對象。
這個模式很簡單,在實際應(yīng)用中可以派上用場。實際上,一些很有名的應(yīng)用就使用了此模式。這些應(yīng)用包括:
Struts - Struts是當(dāng)前開發(fā)Java Web應(yīng)用最受歡迎的基于MVC(模型-視圖-控制)模式的框架。Struts提供了相當(dāng)于ServletRequest 包裝類的org.apache.struts.upload.MultipartRequestWrapper類。 MultipartRequestWrapper覆蓋了getParameter(),getParameterNames(),及 getParameterValues()等方法來實現(xiàn)文件上傳。
Apache Beehive ?C 這個源于BEA的WebLogic專題小組的開源項目,構(gòu)建于Struts之上,并簡化了web應(yīng)用及web服務(wù)的開發(fā)。與ServletRequest包裝類一樣,org.apache.beehive.netui.pageflow.internal包中的PageFlowRequestW
網(wǎng)站標(biāo)題:HttpServletRequest對象介紹
URL鏈接:http://www.5511xx.com/article/dpiepop.html


咨詢
建站咨詢
