比你想象中还要强大的枚举类型---案例篇

  前几天写了一篇介绍枚举功能强大的文章。有几个朋友给我指正说,没有案例单纯描述不够直观。确实啊,在这里我就在写一个案例篇,对上次的文章做补充说明。

  此案例是一个游戏服务器的消息识别器的简化。做过游戏开发都知道,客户端和服务器之间的交互需要定义很多的消息类型,而且这个消息类型是需要不断扩展的。消息识别器就是根据客户端发送过来的消息编码封装成消息实体对象,以供业务逻辑层处理。这里就用这个简化后的消息识别器展示一下枚举的一个应用。(此处主要用作枚举的一个应用实例演示,由于代码做了简化处理,设计上难免会有些不当之处,请见谅)

  消息实体类的一个接口:

public interface IMsg {

	public void setMsgCode(int code);
	
	public void execute();
	
	public void readData(IoBuffer bufer);
	
	public void writerData(IoBuffer bufer);
}

  消息实体类的一个抽象类:

public abstract class AbstractMsg implements IMsg{

	protected int msgCode;
	
	public AbstractMsg(int msgCode){
		this.msgCode = msgCode;
	}
}

  消息实体的一个实现类:

public class TestMsg extends AbstractMsg{

	public TestMsg(int msgCode) {
		super(msgCode);
	}

	private int data1;
	private int data2;
	
	@Override
	public void setMsgCode(int code) {
		this.msgCode = code;
	}

	@Override
	public void execute() {
		//消息处理方法
	}

	@Override
	public void readData(IoBuffer bufer) {
		this.data1 = bufer.getInt();
		this.data2 = bufer.getInt();
	}

	@Override
	public void writerData(IoBuffer bufer) {
		
	}

}

  为了模块化管理,对枚举类型抽出了一个接口,以后一个模块的消息可以注册到一个枚举类上,而这些枚举类都实现此接口

public interface IMsgCodeClass {
	public int getMsgCode();
	public Class<? extends AbstractMsg> getMsgClass();
}

  这是枚举类,可以一个模块一个枚举类,该模块下的消息都注册到该枚举类下

public enum MsgCodeClassConstants implements IMsgCodeClass{
	test(1001,TestMsg.class)//在此就不多罗列一些了
	;

	private int msgCode;
	private Class<? extends AbstractMsg> msgClass;
	
	MsgCodeClassConstants(int msgCode,Class<? extends AbstractMsg> msgClass){
		this.msgCode = msgCode;
		this.msgClass = msgClass;
	}
	
	@Override
	public int getMsgCode() {
		return msgCode;
	}

	@Override
	public Class<? extends AbstractMsg> getMsgClass() {
		return msgClass;
	}

}

  最后是消息识别器类:

public class MsgRecogniser {

	Map<Integer, Class<? extends AbstractMsg>> msges = new ConcurrentHashMap<Integer, Class<? extends AbstractMsg>>();
	
	public void init(){
		MsgCodeClassConstants[] contants = MsgCodeClassConstants.values();
		for(int i=0;i<contants.length;i++){
			msges.put(contants[i].getMsgCode(), contants[i].getMsgClass());
		}
	}
	
	public IMsg getMsg(int msgCode){
		IMsg msg = null;
		Class clazz = msges.get(msgCode);
		try {
			Constructor constructor = clazz.getConstructor(int.class);
			msg= (IMsg) constructor.newInstance(msgCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return msg;
	}
	
}

  消息识别器往往用在解码器里,解码器接收到数据后首先读取消息编码,然后根据编码调用识别器获取消息实体对象,调用消息实体对象的readData方法把客户端数据独到消息实体对象中。

  以后要扩展消息时,只需要编写消息实体类,然后注册到枚举类中就可以了。:)

原文地址:https://www.cnblogs.com/metoy/p/3900321.html