По совпадению, я недавно создал проект, который в значительной степени соответствует тому, что вы описываете.Использование неизменяемых моделей данных дает огромные преимущества, но многие технологии сериализации, по-видимому, подходят к неизменности как к запоздалой мысли.Я хотел что-то, что исправило бы это.
Мой проект, Grains , использует генерацию кода для создания неизменной реализации модели предметной области.Реализация является достаточно общей, чтобы ее можно было адаптировать к различным средам сериализации.До сих пор поддерживаются MessagePack, Jackson, Kryo и стандартная сериализация Java.
Просто напишите набор интерфейсов, которые описывают модель вашего домена.Например:
public interface ServiceId {
enum ServiceType {Foo, Bar}
String getName();
ServiceType getType();
}
public interface ServiceConfig {
enum JvmConfig {DEFAULT, SPECIAL}
String getHost();
int getPort();
String getUser();
JvmConfig getType();
}
public interface ServiceInfo {
ServiceId getId();
ServiceConfig getConfig();
}
Плагин Grains Maven затем генерирует неизменные реализации этих интерфейсов во время компиляции.(Источник, который он генерирует, предназначен для чтения людьми.) Затем вы создаете экземпляры своих объектов.В этом примере показаны два шаблона построения:
ServiceIdGrain id = ServiceIdFactory.defaultValue()
.withType(ServiceType.Foo)
.withName("my-foo-service");
ServiceConfigBuilder cfg = ServiceConfigFactory.newBuilder()
.setHost("localhost")
.setPort(8080)
.setUser("abc")
.setType(JvmConfig.DEFAULT);
ServiceInfoGrain info = ServiceInfoFactory.defaultValue()
.withId(id)
.withConfig(cfg.build());
Не так просто, как ваши public final
поля, я знаю, но наследование и композиция невозможны без методов получения и установки.И эти объекты легко читаются и пишутся с помощью MessagePack:
MessagePack msgpack = MessagePackTools.newGrainsMessagePack();
byte[] data = msgpack.write(info);
ServiceInfoGrain unpacked = msgpack.read(data, ServiceInfoGrain.class);
Если фреймворк Grains не работает для вас, вы можете проверить его шаблоны MessagePack .Вы можете написать универсальный TemplateBuilder
, который использует отражение, чтобы установить конечные поля вашей рукописной модели предметной области.Хитрость заключается в том, чтобы создать пользовательский TemplateRegistry
, который позволяет регистрировать вашего собственного сборщика.