2012-02-06 58 views
1

我在寫一個充當前端控制器的Java servlet。爲了執行功能,我使用了域命令模式。目前,我正在初始化所有命令並將它們存儲在一個映射中,命令的名稱(字符串)作爲鍵和對象作爲值。每當servlet接收的請求,我通過URL將命令傳遞查詢作爲獲取地圖中的命令:Servlet和命令模式,編譯vs運行時?

// at init 
Hashmap<String, DomainCommand> commands = new Hashmap<String, DomainCommand>(); 
commands.put("someCommand", new SomeCommand()); 

// at request 
String command = request.getParameter("command"); 
DomainCommand c = commands.get(command); 
c.execute(); 

這工作得很好,我想要做什麼,因爲我的DomainCommands沒有階級屬性被線程之間共享。另一種方法是使用反射來創建對象,如下所示:

String command = request.getParameter("command"); 
DomainCommand c = Class.forName(command).newInstance(); // assuming in same (default) package 
c.execute(); 

這兩個工作。從節省性能/記憶的角度來看哪個更好?

回答

3

性能

當使用Map的唯一成本正在訪問一個HashMap(忽略不計)。另一方面反思可能需要更多的時間並且不太安全 - 請記住,您必須確保用戶不會通過僞造command,允許他運行任意代碼。

內存

當創建在啓動時,他們將在老一代結束了一段時間後,因此不會對大多數的時間是被垃圾回收。另一方面,當每個請求創建時,他們很可能會立即收集垃圾。所以總的來說,內存佔用將是可比較的,除了第二種方法需要mor GC運行。

總而言之,命令圖是一種更好的方法。順便說一句,如果你的DI框架像Spring或者Guice(除非這對你來說是一種矯枉過正)或者像Struts/Spring MVC這樣的web框架,它們會爲你完成同樣的工作。

+0

這是一個學校項目,所以我必須自己實現大部分功能,但是謝謝你回答我的問題。 – 2012-02-06 21:14:29

1

HashMap中存儲命令的第一種方法更好。第二種方法的問題是,每次執行該命令時都必須加載命令類。

事實上,像Struts這樣的框架,其精確地以命令模式與控制器Servlet作爲前端控制器,個別動作類作爲命令。

1

從性能的角度來看,你提到的第一種方法肯定更快。

下列選項如何?使用Visitor模式的命令

  1. 存儲您的命令豆類和JNDI它的名字做命令bean查找(從請求)使用(有從JNDI檢索命令服務)
  2. IoC框架(Spring)所有命令bean都從容器啓動初始化並查找命令在應用程序上下文中完成

性能方面我更喜歡第三個選項。

0

如何將兩個選項合併在一起?

Struts完全一樣。它包含一個Map緩存Servlet請求的所有命令。如果該命令不存在,則會創建該命令的newInstance()(就像您創建的選項2一樣)。

這樣做的好處是可以更快地執行您的過程:從緩存中檢索命令,否則創建一個新的命令&並將創建的新命令存儲在緩存中。這肯定比選項2更快。

1

你從性能/內存節省的角度特別要求答案,其他答案回答這個問題。我同意在這方面Map方法可能更好。

但是,在此之前,您應該確定這是一個擔心甚至擔心的問題;我假設一個調用servlet的網絡開銷遠遠超過了一個簡單字符串的單個HashMap查找。

更大的問題應該是清晰度和可維護性。在這方面,以及,我要說的是,地圖的做法優越得多,因爲它:

  • 的API(命令參數的合法值)不綁的執行(類名稱)
  • 清楚地說明哪些類將用作命令,哪些不是(如果您稍後想要進行更改,則非常重要)
  • 允許API更靈活(例如,您可以允許command參數不區分大小寫,或者將多個命令映射到同一類)

引用Zen of Python:「顯式比隱式更好」。