我正在编写一个充当前端控制器的Java servlet。为了执行我正在使用域命令模式的功能。目前,我正在初始化我的所有命令并将它们存储在一个映射中,命令的名称(字符串)作为键,对象作为值。每当servlet收到请求时,我都会通过从url传递命令查询来从地图获取命令:
// 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();
这两项都有效。从性能/内存节省的角度来看哪个更好?
答案 0 :(得分:3)
使用Map
时,唯一的代价是访问HashMap
(可忽略不计)。另一方面,反思可能需要更多时间并且不太安全 - 记住你必须确保用户没有通过伪造command
,允许他运行任意代码。
在启动时创建DomainCommand
时,它们将在一段时间后结束于旧代,因此大部分时间都不会进行垃圾回收。另一方面,每次请求创建时,他们很可能会立即进行垃圾回收。总的来说,内存占用量是可比较的,除了第二种方法需要运行GC运行。
总而言之,命令图是一种更好的方法。顺便说一句,如果您的DI框架像Spring或Guice(除非这对您来说太过分了)或者像Struts / Spring MVC这样的Web框架,他们将为您完成同样的工作。
答案 1 :(得分:1)
将命令存储在HashMap
中的第一种方法更好。第二种方法的问题是每次执行该命令时都必须加载命令类。
实际上像Struts这样的框架,它精确地在命令模式上使用Controller Servlet作为前端控制器,并将各个动作类作为命令。
答案 2 :(得分:1)
从性能角度来看,你提到的第一种方法肯定更快。
以下选项如何?
表现方面我更喜欢第三种选择。
答案 3 :(得分:1)
你从性能/内存保存的角度特别要求答案,其他答案回答了这个问题。我同意Map方法在这方面可能更好。
然而,在此之前,你应该确定这是一个令人担忧的问题。我假设一次调用你的servlet的网络开销远远超过短字符串的单个HashMap查找。
更大的问题应该是清晰度和可维护性。在这方面,我会说Map方法更优越,因为它:
引用Zen of Python:“显式优于隐式”。
答案 4 :(得分:0)
如何将两个选项合并在一起?
Struts完全一样。它包含一个Map
,用于缓存Servlet请求的所有命令。如果命令不存在,则会创建命令的newInstance()
(就像您创建的选项2一样)。
这样做的好处是可以更快地执行您的过程:从缓存中检索命令,否则创建一个新的&amp;并将创建的新命令存储在缓存中。它肯定比选项2快。