Servlet與模板方法模式
----Head First Pattern之模板方法模式
這
年頭大家都用struts,或者其他MVC框架,很少有人直接用Servlet了吧,但是相信大部分人都應該知道怎么寫Servlet的吧,繼承
HttpServlet類,覆蓋里面的doGet、doPost方法即可,大部分情況下,我們都是對GET和POST一樣處理,一般也就這么寫了:
public MyServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response){
// 處理
}
public void doPost()HttpServletRequest request, HttpServletResponse response){
// 不關心get、post請求,因此post處理直接調用get處理
doGet(request, response);
}
}
Servlet只要在web.xml中部署好之后,就可以處理瀏覽器的請求了。上面代碼可以看出來,doGet方法處理瀏覽器的GET請求,doPost處理POST請求。
Servlet是由Tomcat之類的servlet容器來調用處理瀏覽器請求的,并需要集成基類HttpServlet,如果大家查看HttpServlet源碼的時候,就會發現,其實里面有一個
protected void service(
HttpServletRequest req,
HttpServletResponse resp)
方法,servlet容器實際調用的是service方法,service方法的實現就是根據HTTP請求的類型(GET、POST,還是其他),將處理委派給doGet、doPost等方法,由這些子類的方法來最終處理瀏覽器的請求。
由此可以看出,HttpServlet定義了一個處理的框架或者說模板,實現Servlet只需繼承HttpServlet并實現doGet、doPost等方法即可。
是引出模板方法模式定義的時候了,
模板方法模式:在一個方法中定義一個算法的骨架,將某些步驟推遲到子類中實現。模板方法允許子類重新定義算法的某些步驟,而不改變算法的結構。
簡單UML類圖如下:
簡單實現一個抽象類:
public abstract Template{
public void
final templateMethod(){
step1();
step2();
hook();
}
public abstract void step1();
public abstract void step2();
public void hook(){}
}
這個抽象類,定義了一個算法的骨架,需要step1、step2,都是抽象方法,需要子類來實現。而templateMethod是final的,即不允許子類覆蓋。其中定義了方法的步驟,step1、step2。
如下為具體實現:
public ConcreteTemplate extends Template{
public void step1(){System.out.println("step1");}
public void step2(){System.out.println("step2");}
public void hook(){System.out.println("hook");}
public static void main(String[] args){
Template temp = new ConcreteTemplate();
temp.templateMethod();
}
}
可以看到其中加入了一個hook方法,即鉤子方法。hook方法在抽象類中的實現為空,是留給子類做一些可選的操作。如果某個子類需要一些特殊額外的操作,則可以實現hook方法,當然也可以完全不用理會,因為hook在抽象類中只是空方法而已。
其他擴展:
1.可以定義多個hook方法
2.hook方法可以定義一個返回為boolean的方法,有子類來決定是否調用hook方法。
eg:抽象類的templateMethod可以這樣實現:
public void
final templateMethod(){
step1();
step2();
if(allowHook())
hook();
}
public boolean allowHook(){return true;}
public void hook(){}
子類中可以覆蓋allowHook,以決定是否調用hook方法。
3.抽象類定義的步驟,可以有默認實現,而非全是abstract方法。HttpServlet中已經有doGet、doPost等方法的默認實現,大家可以參考其源碼實現。
更好的一個模板方法的例子是Applet,實現自己的Applet,必須繼承自Applet,里面實現init、start、stop、destroy等方法即可。這些方法都是有默認實現的,如果看源碼,可以發現默認實現其實都是空。
了解模板方法模式之后,大家可能意識到Servlet并且完全按照模板方法定義的那樣,而是有一些區別,比如提供默認doGet、doPost的實現等。這都說明,在實際編程中,并非生搬硬套設計模式,而是根據實際,會做些變動或變形,但其本質不變。
不能為了模式而模式。那究竟什么時候需要設計模式呢?個人理解,當你發現你的類有問題的時候,比如有重復代碼了,感覺有些不對勁了,感覺不適應以后的擴充了,這時候不妨考慮下,是不是該設計模式出場了。。
純粹個人理解。。有不當之處,請及時拍磚。。