2012-08-02 97 views
8

我在客户端 - 服务器体系结构中使用协议缓冲区作为有线数据格式。域对象(java bean)将经历以下生命周期。协议缓冲区和OO设计

  1. ,用于客户端业务逻辑
  2. 转换为protobuf的格式
  3. 传输到服务器
  4. 转换回用于服务器端业务逻辑域对象

"Protocol Buffers and O-O Design" ProtoBuf文档中的部分建议将生成的类包装在适当的域模型中。

我想找出最好的选择。

例如,我有一个简单的原型定义。

package customer; 

option java_package = "com.example"; 
option java_outer_classname = "CustomerProtos"; 

message Customer { 
    required string name = 1; 
    optional string address = 2; 
} 

这就是域模型的定义方式。如您所见,数据完全存储在原始生成器对象中。

package com.example; 

public class CustomerModel 
{ 
    private CustomerProtos.Customer.Builder builder = CustomerProtos.Customer.newBuilder(); 

    public String getName() 
    { 
     return builder.getName(); 
    } 

    public void setName(String name) 
    { 
     builder.setName(name); 
    } 

    public String getAddress() 
    { 
     return builder.getAddress(); 
    } 

    public void setAddress(String address) 
    { 
     builder.setAddress(address); 
    } 

    public byte[] serialize() 
    { 
     return builder.build().toByteArray(); 
    } 

} 

这是一个很好的做法吗?因为这些对象用于生命周期的所有阶段,但我们只需要在客户端 - 服务器传输阶段使用protocolbuf格式。

当原型定义非常复杂且嵌套时,在访问原型构建器类getter/setter方法时是否存在性能问题?

回答

5

我没有协议缓冲区的经验,但我会而不是建议实现您的域对象为特定的序列化/传输框架定制。你可能会后悔的。

软件应用程序的领域对象和逻辑应尽可能独立于特定的实现问题(在您的案例序列化/传输中),因为您希望您的领域在未来易于理解并可重复使用/可维护。

如果要定义你的域对象的独立序列化/转移的,你有两个选择:

  1. 系列化/转让之前,将信息复制到协议 缓冲区特定的对象,并将它们发送到您的服务器。那你 将不得不将信息复制回你的域对象。
  2. 使用非协议序列化库(如KryoProtoStuff)将域对象直接转移到 服务器。

选项1的缺点是您的域被定义了两次(这对于修改是不可取的)和信息的复制(这产生了容易出错和不可维护的代码)。

选项2的缺点是你丢失了schema evolution(尽管ProtoStuff显然为supports it)并且完整(可能是大的)对象图被序列化和传输。尽管可以在序列化/传输之前修剪对象图(手动或使用JGT)。

2

我们制定了一个protobuf-converter来解决将您的域模型对象转换为Google Protobuf消息的问题,反之亦然。

如何使用它:

  • 类必须由@ProtoClass标记 annotaion包含 :

    必须被转化为protobuf的消息必须满足下列条件:领域模型类有关protobuf消息类的参考。

  • 类字段必须标注@ProtoField注释。这些字段必须有getter和setter。

例如:

@ProtoClass(ProtobufUser.class) 
public class User { 

    @ProtoField 
    private String name; 
    @ProtoField 
    private String password; 

    // getters and setters for 'name' and 'password' fields 
    ... 
} 

代码转换User实例成相关的protobuf消息:

User userDomain = new User(); 
... 
ProtobufUser userProto = Converter.create().toProtobuf(ProtobufUser.class, userDomain); 

代码向后转换:

User userDomain = Converter.create().toDomain(User.class, userProto); 

对象列表的转换是类似于单个对象转换。