我有一个接收包(字节数组)的套接字类。每个包都有一个整数来标识其类型。 switch 语句中的每个 case 如下所示:
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 语句。
问题:
我的解决这个问题的想法正确吗?如果没有请赐教。 如何实现到目前为止没有意义的代码的最后部分(如果这是正确的方法)?
编辑:数据包是抽象类Packet
的对象,它由每个特殊数据包(如PingRequest
)扩展
最佳答案
看来你的想法可行。我认为代码需要是这样的:
Class<? extends Packet> myClass = PacketAbstract._packetTypes.get(packet.getHeader().getID());
Constructor<Packet> ct = myClass.getConstructor(data.getClass());
Packet specialPacket = ct.newInstance(data);
specialPacket.setHeader(data);
packet = specialPacket;
但是,在我看来,使用反射通常是最后的手段。考虑研究其他模式,例如 Visitor Pattern这可能有助于解决此类问题。
另一种选择是将每个标识符的正确具体Class
嵌入到枚举中,如下所示:
enum PacketID {
private int id;
private int size;
private Class<? extends Packet> subClass;
private PacketID(int id, int size, Class<? extends Packet> subClass) {
this.id = id;
this.size = size;
this.subClass = subClass;
}
ERROR( 1, 100, Error.class),
PINGREQ(2, 25, PingRequest.class);
}
这还允许您抽象出大小检查,这是我在第一个 HashMap
解决方案中没有看到的,并且可能完全跳过 HashMap
。
编辑:将参数更改为getConstructor()
,因为您似乎使用字节数组而不仅仅是Byte
。
编辑:使用枚举字段添加了第二个替代解决方案。
关于java - 用 HashMap 替换 switch 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16318836/