以前用的最多的是单例模式(singleton),也在原来的项目中用过策略模式,只是自己每次在写代码的时候并没有刻意去强加一些模式去实现。
前段时间读了《重构-改善既有代码的设计》之后,觉得有必要有所为了,于是就拿了为项目写的聊天系统来开刀了。
聊天项目是用java写的,用到了mina框架,而以前聊天逻辑处理类就是一个单例模式的Messageservice,然后在mina的messagehendler的receiveMessage()里面调用了。
而MessageService里面的handleMessage(IoSession session, Object message)方法里面,用到了各种if、else去区分每个message是哪种类型的,是玩家群发世界聊天消
息的还是系统消息亦或是登录聊天系统的消息等等,如果消息类型很少还好,但是消息类型多起来,譬如后面又添加私聊功能等,这一个方法就会很庞大。
public void handleMessage(IoSession session, IMessage message){
logger.info("【received】:" + message.toString());
message.getHanle().execute(message, session, store);
if(message instanceof CSLoginMessage){
...
} else if(message instanceof CSSystemMessage){
...
} else if(message instanceof CSWorldMessage){
...
}
}
代码可读性就会差。于是我就根据《重构...》书中所讲的,尽量少用条件判断结构if..else和switch等,将代码进行浓缩。
- 定义一个接口叫做IHandle,里面有个方法execute(),方法就是用来执行每个if块里面的逻辑代码
public Interface IHandle{ public void execute(IoSession, IMessage message); }
- 有多少if逻辑块就新建多少个类去实现IHandle接口,然后将对应的execute方法里面的逻辑代码用if块里面的代码去移植。譬如这里就有3个handle的继承类分别命名为:LoginMessageHandler,SystemMessageHandler,WorldMessageHandler.这个时候我们代码就可以换成这样了
public void receiveMsg(IoSession session, IMessage message){ logger.info("【received】:" + message.toString()); message.getHanle().execute(message, session, store); if(message instanceof CSLoginMessage){ new LoginMessageHandler().execute(session, message) } else if(message instanceof CSSystemMessage){ new SystemMessageHandler().execute(session, message) } else if(message instanceof CSWorldMessage){ new WorldMessageHandler().execute(session, message) } }
- 到这里只是将if..else里面的逻辑代码进行了封装,并没有把条件结构去掉。如何去掉呢?我们就将每个handler和message进行对应即可,也就是将每个Message加一个IHandle类型的属性或者相对应的getHandle方法。用LoginMessage举例
import org.apache.mina.core.buffer.IoBuffer; import com.zxhd.chat.handler.IHandle; import com.zxhd.chat.handler.script.HandleManager; import com.zxhd.chat.util.IoBufferUtil; public class CSLoginMessage extends BaseMessage { private static final long serialVersionUID = -9167867242751526528L; ... @Override public IHandle getHanle() { return new LoginMessageHandler(); } }
接下来就可以把MessageService.handleMessage方法里的if..else去掉了。代码如下:
public void handleMessage(IoSession session, IMessage message){ logger.info("【received】:" + message.toString()); message.getHanle().execute(session, message); }
ps:其实在游戏里面道具的使用或者道具数量的增加也可以用这种结构模式来做