游戏开发笔记:protobuf避免重复代码newBuilder
Posted 程序员小毛驴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏开发笔记:protobuf避免重复代码newBuilder相关的知识,希望对你有一定的参考价值。
最近大家都在忙着功能优化和BUG,而我却比较闲,开发的模块没有什么BUG也没什么需要优化的,便抽些时间来改下正在开发项目中的一些坏代码。
坏代码一:
```
//坏代码
SC_ResponseMsgProto.Builder responseMsgBuilder = SC_ResponseMsgProto.newBuilder();//重复一
DataMsgProto.Builder dataMsgBuilder = DataMsgProto.newBuilder();//重复二
dataMsgBuilder.setB(b.build());
responseMsgBuilder.setDataMsg(dataMsgBuilder.build());//重复三
responseMsgBuilder.setA(a.build());
sendMsgToClient(channel, responseMsgBuilder.build());//重复四
```
```
message SC_ResponseMsgProto
optional DataMsgProto dataMsg = 1;
optional A a = 2;
message DataMsgProto
optional B b = 1;
message A
optional int32 num = 1;
optional C c = 2;
message B
optional int32 num = 1;
message C
optional int32 num = 1;
```
项目客户端和服务器采用的是Google的protobuf协议,数据结构设计采用的是森林结构。如上所示,SC_ResponseMsgProto是最顶层对象,在最顶层对象下有多个不同类别的子对象,如A、B、DataMsgProto,子对象下还拥有一些不同类别的子对象C,最终成为一个森林结构,森林里每个根对象都是一颗树。对象间有时有一些引用关系,比如,A对象使用了C引用。这样的设计在开发中是比较常见的,但是我们在项目中使用时比较流水账,大量的顶层对象代码在不同地方重复出现在项目中。对于每个程序员员来说,避免重复代码是大家都想做的。于是我大约花了不到30行代码来避免以上标注的四个重复地方,代码如下:
```
/**
* 下发给客户端的消息
*/
private final LinkedList<GeneratedMessageLite> responseMsgs = new LinkedList<>();
//添加消息
public void putMsg(GeneratedMessageLite msg)
synchronized (responseMsgs)
responseMsgs.add(msg);
//发送消息
public void sendMsg(Channel channel)
//和客户端通讯的数据
SC_ResponseMsgProto.Builder responseMsgBuilder = SC_ResponseMsgProto.newBuilder();
DataMsgProto.Builder dataMsgBuilder = DataMsgProto.newBuilder();
try
for (GeneratedMessageLite messageLite : responseMsgs)
if (messageLite instanceof A)
responseMsgBuilder.setA((A) messageLite);
else if(messageLite instanceof B)
dataMsgBuilder.setB((B) messageLite);
responseMsgBuilder.setDataMsg(dataMsgBuilder.build());
sendMsgToClient(channel, responseMsgBuilder.build());
catch (Exception e)
e.printStackTrace();
logger.error(e.getMessage(), e);
finally
responseMsgs.clear();
```
```
//优化后代码
role.putMsg(a.build());
role.putMsg(b.build());
role.sendMsg(channel);
```
虽然避免了重复代码,但是细心的童鞋可能发现在sendMsg()里意外的出现了不是最顶层对象的DataMsgProto.如果当DataMsgProto里出现相同类型的b、b1对象时,那就无法从类型上去区分它们了。我想到的解决方案是使用自定义唯一key来区分或者在定义协议时不允许出现相同类型的(这里并不推荐,毕竟有时候多个类型能解决不少问题)。
有同学可能会想能否使用变量名称b作为唯一区分标识,这个是不可以的,因为java不能获取变量名字,[详细参考R大在知乎上的回答](https://www.zhihu.com/question/29643012)。
```
message DataMsgProto
optional B b = 1;
optional B b1 = 2;
```
作者: 小毛驴,一个游戏人
梦想:世界和平
原文地址: http://blog.csdn.net/liulongling
若有错误之处,请多多谅解并欢迎批评指正
以上是关于游戏开发笔记:protobuf避免重复代码newBuilder的主要内容,如果未能解决你的问题,请参考以下文章
我可以重复使用对象实例来避免使用 protobuf-net 进行分配吗?