java用HashMap替换switch语句
我有一个socket类,它接收包(字节数组)。每个包都有一个整数以标识其类型。switch语句中的每种情况如下所示:
switch(packet.getHeader().getID()) {
case PingRequest.ID:
if(data.length != PingRequest.SIZE)
return null;
PingRequest pingRequest = new PingRequest(data); /* specific parsing of the byte array */
pingRequest.setHeader(data); /* method of the abstract class */
packet = pingRequest;
break;
case Error.ID:
if(data.length != Error.SIZE)
return null;
Error error = new Error(data);
error.setHeader(data);
packet = error;
break;
...
每个数据包都有不同的信息,这就是为什么每个数据包都有不同的构造函数(从字节数组data
创建数据包成员)
由于每个案例看起来都有些相似(而且有很多),我认为应该使用HashMap对其进行优化:
public static HashMap<Integer, Class<?>> _packetTypes = new HashMap<Integer, Class<?>>();
_packetTypes.put(PingRequest.ID, PingRequest.class);
我现在想要实现的是这样的目标:
Class<?> myClass = PacketAbstract._packetTypes.get(packet.getHeader().getID());
Class[] cArg = new Class[1];
cArg[0] = Byte.class;
Constructor<?> ct = myClass.getConstructor(cArg);
/* Doesn't make any sense from here on */
myClass specialPacket = ct.newInstance(data);
specialPacket.setHeader(data);
packet = specialPacket;
因此,基本的想法是创建一个hashmap,其中包含数据包id和相应的数据包类,允许我创建专门的数据包。最后一段代码是用来替换我的switch语句的
问题:
我的解决方法正确吗?如果没有,请告诉我。 我如何实现我的代码的最后一部分,这到目前为止还没有意义(如果这是正确的方法)
EDIT:packet是抽象类Packet
的一个对象,它被像PingRequest
这样的每个特殊包扩展
# 1 楼答案
# 2 楼答案
你能不能用工厂模式(例如http://alvinalexander.com/java/java-factory-pattern-example)
比如:
# 3 楼答案
看来你的主意行得通。我认为代码应该是这样的:
然而,在我看来,使用反射通常是最后的手段。考虑查看其他模式,如Visitor Pattern,这可能有助于解决这类问题。
另一种选择是将每个标识符的正确具体
Class
嵌入一个枚举中,如下所示:这也将允许您抽象掉大小检查,我在您的第一个
HashMap
解决方案中没有看到这一点,并且可能完全跳过HashMap
编辑:将参数更改为
getConstructor()
,因为似乎您使用的是字节数组,而不仅仅是Byte
。 编辑:添加了第二个使用枚举字段的替代解决方案