我将首先描述用例来澄清问题:
我正在编写一个IMAP服务器,该服务器从客户端接收命令。如果处于正确的状态,它将从网络套接字读取一个令牌,并将该令牌解释为命令的名称。截至目前,我的服务器从令牌中读取命令的名称,并使用switch
语句执行相应的代码。
这是它的一瞥:
case ("CAPABILITY"): this.executeCapability(tag); break;
case ("NOOP"): this.executeNoop(tag); break;
case ("LOGOUT"): this.executeLogout(tag); break;
case ("LOGIN"): this.executeLogin(tag, args); break;
我的问题是:是否有客观上更可取的理由使用事件来调度命令?性能会更好吗?有安全优势吗?
我提议的替代方案可能看起来像这样:
server.on("CAPABILITY", executeCapability);
server.on("NOOP", executeNoop);
server.on("LOGOUT", executeLogout);
server.on("LOGIN", executeLogin);
答案 0 :(得分:1)
其他代码更容易扩展和使用事件。他们生活在一个已经存在基础架构的系统中,其他任何人都可以收听这些事件。如果您要调用一个函数,传递一个参数,然后使用switch语句进行分派,则这是一个自定义的非标准接口,并且如果其他人(甚至您自己代码的另一部分)想要侦听这些事件之一并自己采取行动,然后他们必须构建一些自己的自定义代码以某种方式做到这一点。
如果使用事件,则该基础结构已经存在。他们可以使用自己的监听器收听事件。
这是一个小例子。想象一下,出于性能原因,您正在为每个用户从数据库缓存一些数据。当用户注销时,您想清除缓存。您的缓存系统是其自己的模块,因为它可以在其他应用程序中重用。如果使用事件,则高速缓存可以仅为注销事件设置其自己的事件侦听器,并且可以在给定用户注销时进行自己的内务处理。在开关设计中,您可能必须在executeLogout()
函数中插入代码才能调用缓存中的某些方法。那会起作用,但是代码并不会像可能的那样被封装。现在,您在logout()
方法中有了缓存逻辑,在事件系统中不需要缓存逻辑,因为缓存可以自己监视所有感兴趣的事件。
我并不是说这是一个杀手example的例子,这意味着您必须以一种或另一种方式来做。只是展示了事件的一些体系结构优势,它使子系统可以更轻松地访问事件,从而使子系统可以更轻松地管理自己(封装更多的代码)。
我认为不会有有意义的性能差异。如果您处于对性能敏感的严格循环中,则事件子系统可能会引入更多的函数调用来进行分派,而不是使用switch语句,但是对于常规代码而言,这不是必然的。