java中有多态的概念,protobuf本身没有多态的概念,但是它有一个扩展的概念。

以聊天消息为例,先看下面这个类图,基类是ChatMessage,子类TextMessage和ImageMessage。

ChatMessage

  • id:消息ID
  • from:发送者
  • to:接收者
  • type:消息类型(可能为点对点聊天,或者聊天室聊天)
  • contentType:消息内容类型(文本消息、图片消息等)

TextMessage

  • content:文本内容

ImageMessage

  • url:图片的地址

父类ChatMessage的schema如下,其中声明了一个ContentType枚举,有两个值text和image,分别代表文本和图片,根据content_type可以获得扩展信息。

 package polymorphism;

 option java_package = "polymorphism";
option java_outer_classname = "BaseChatMessageProtos"; message ChatMessage {
optional string id = 1;
optional string from = 2;
optional string to = 3; enum Type {
chat = 0;
groupchat = 1;
error = 2;
} optional Type type = 4; enum ContentType {
text = 0;
image = 1;
} optional ContentType content_type = 5; extensions 100 to 299;
}

子类TextMessage和ImageMessage的schema如下

 package polymorphism;

 option java_package = "polymorphism";
option java_outer_classname = "ConcreteChatMessageProtos"; import "polymorphism/base_chat_message.proto"; message TextBody {
extend ChatMessage {
optional TextBody body = 100;
} optional string content = 1;
} message ImageBody {
extend ChatMessage {
optional ImageBody body = 101;
} optional string url = 1;
}

根据schema生成的java类,参考protobuftest工程polymorphism包路径下的BaseChatMessageProtos类和ConcreteChatMessageProtos类。

protobuftest工程下载地址:http://pan.baidu.com/s/1jIGWBf4

下面是序列化和反序列化的代码

1-8行:构造文本消息

12行:获得序列化字节数组

14-16行:创建并初始化扩展注册中心

18行:反序列化获得ChatMessage

21-23行:生成contentType和Extension(消息内容扩展描述)的映射关系,方便反序列化时获得扩展信息body

28行:根据contentType获得对应的TextMessage扩展描述,然后获得TextBody中定义的body

         ChatMessage textMessage = ChatMessage.newBuilder()
.setId("123")
.setFrom("100@pingan.com.cn")
.setTo("101@pingan.com.cn")
.setType(Type.chat)
.setContentType(ContentType.text)
.setExtension(TextBody.body, TextBody.newBuilder().setContent("hello world").build())
.build(); System.out.println("*****before serialize=" + textMessage); byte[] bytes = textMessage.toByteArray(); ExtensionRegistry registry = ExtensionRegistry.newInstance();
registry.add(ImageBody.body);
registry.add(TextBody.body); ChatMessage deserializedMessage = ChatMessage.parseFrom(bytes, registry);
System.out.println("*****after deserialize"); Map<ChatMessage.ContentType, Extension<ChatMessage, ?>> contentType2ExtensionBody = new HashMap<ChatMessage.ContentType, Extension<ChatMessage, ?>>();
contentType2ExtensionBody.put(ContentType.text, TextBody.body);
contentType2ExtensionBody.put(ContentType.image, ImageBody.body); ContentType contentType = deserializedMessage.getContentType();
switch (contentType) {
case text:
TextBody deserializedTextBody = (TextBody) deserializedMessage.getExtension(contentType2ExtensionBody.get(contentType));
System.out.println("body=" + deserializedTextBody);
break;
case image:
ImageBody deserializedImageBody = (ImageBody) deserializedMessage.getExtension(contentType2ExtensionBody.get(contentType));
System.out.println("body=" + deserializedImageBody);
break;
default:
break;
}

25-37行:根据contentType获取对应扩展信息的body。注意:可以使用多态消除case语句

以后每增加一种新的消息内容类型,在反序列化的时候只需要在contentType和Extenstion(消息内容扩展描述)的映射关系中新增一个映射,然后新增一个获取对应消息内容类型的body的子类,无需修改其他的代码。

Protocol Buffer多态的更多相关文章

  1. 从零开始山寨Caffe·伍:Protocol Buffer简易指南

    你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...

  2. Protocol Buffer搭建及示例

    本文来源:http://www.tanhao.me/code/150911.html/ Protocol Buffer(简称Protobuf或PB)是由Google推出的一种数据交换格式,与传统的XM ...

  3. [原创翻译]Protocol Buffer Basics: C#

    Protocol Buffer 基础知识:c#    原文地址:https://developers.google.com/protocol-buffers/docs/csharptutorial   ...

  4. Google Protocol Buffer 的使用和原理[转]

    本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...

  5. Google Protocol Buffer 的使用

    简介 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 ...

  6. 学习Google Protocol buffer之语法

    上一篇结尾的时候问了几个问题,其实主要就是这个protoBuffer协议的语法,弄清楚语法后边才好开展工作嘛,不然大眼而对小眼儿,互相不认识,就没法玩耍了.其实就是学习怎么用google提供的这套 p ...

  7. 学习Google Protocol buffer之概述

    XML这种属于非常强大的一种格式,能存储任何你想存的数据,而且编辑起来还是比较方便的.致命的缺陷在于比较庞大,在某些情况下,序列化和解析都会成为瓶颈.这种对于实时性很强的应用来说,就不太适合了,想象下 ...

  8. Google Protocol Buffer 简单介绍

    以下内容主要整理自官方文档. 为什么使用 Protocol Buffers .proto文件 Protocol Buffers 语法 编译.proto文件 Protocol Buffers API 枚 ...

  9. Ggoogle Protocol Buffer的使用 (基于C++语言)

    首先说明的是Protocol Buffle是灵活高效的.它的一个很好的优点(很重要的,我认为)就是后向兼容性--当我们扩展了了.proto文件后,我们照样可以用它来读取之前生成的文件. 之前已经写了关 ...

随机推荐

  1. R语言学习笔记:小试R环境

    买了三本R语言的书,同时使用来学习R语言,粗略翻下来感觉第一本最好: <R语言编程艺术>The Art of R Programming <R语言初学者使用>A Beginne ...

  2. Unable to execute dex: Multiple dex files define Lcom/kenai/jbosh/AbstractAttr

    出现该问题应该是导入项目的android版本问题.   编译的时候把build path 下 source选项卡中的libs去掉就正常了.   http://blog.csdn.net/e421083 ...

  3. iOS-协议与代理<转>

    代理,又称委托代理(delegate),是iOS中常用的设计一种模式.顾名思义,它是把某个对象要做的事情委托给别的对象去做.那么别的对象就是这个对象的代理,代替它来打理要做的事.反映到程序中, 首先要 ...

  4. android 之 桌面的小控件AppWidget

    AppWidget是创建的桌面窗口小控件,在这个小控件上允许我们进行一些操作(这个视自己的需要而定).作为菜鸟,我在这里将介绍一下AppWeight的简单使用. 1.在介绍AppWidget之前,我们 ...

  5. linux---文本编辑vi

    本文摘自:鸟哥的linux私房菜

  6. [转]个人源码管理:如何在本机配置自己的SVN Repository (图解)

    本文转自:http://blog.csdn.net/wikijava/article/details/6245588 Repository 即源码的集中存放处,所有修改后提交的源码就是保存在这里,并在 ...

  7. Effective Java 77 For instance control, prefer enum types to readResolve

    The readResolve feature allows you to substitute another instance for the one created by readObject ...

  8. for循环练习题

    ■■■■■■■■■■■■■■■■■■■■■■■■■ 代码: <script> for(i=0;i<5;i++) { for(j=0;j<5;j++) { document.wr ...

  9. XNote Ver:0.79

    隐藏主窗后,双击小图标显示主窗. 支持拖拉网页文字到小图标上,直接在当前项目上创建下级资料项目. 项目分类限50个汉字.

  10. 21 数据库编程 - 《Python 核心编程》