I am dealing with a set of message objects, each of which has a unique identifier corresponding to them. Each message can be constructed either from a Map, or from a ByteBuffer (the messages are binary, but we know how to transfer to and from a binary representation).
The current implementation for constructing these messages is roughly as follows:
public static Message fromMap(int uuid, Map<String, Object> fields) {
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessage(fields);
.
.
.
default:
// Error
return null;
}
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessage(buffer);
.
.
.
default:
// Error
return null;
}
}
Now, Josh Bloch’s Effective Java talks about Item 1: Consider static factory methods instead of constructors, and this seems to be a place where this pattern is useful (clients don’t directly access the constructors of the Message subtypes; instead they go through this method). But I do not like the fact that we have to remember to keep two switch statements updated (violates the DRY principle).
I would appreciate any insight into the best way to accomplish this; we’re not caching objects (each call to fromMap or fromByteBuffer will return a new object), which negates some of the benefit of using a static factory method like this. Something about this code strikes me as wrong, so I would love to hear the community’s thoughts on whether this is a valid way to construct new objects, or if not what a better solution would be.
Maybe you could create an interface MessageFactory and implementations of it:
next, a method getFactoryFromId in the same class as the methods above:
However, instead of this, it is better to create a Hashmap containing the ids and the factories, so you don’t have to create a new Factory object everytime you are creating a message. See also the comment below.
and your methods:
This way, you are using the factory pattern, and there is no need to have two times the same switch statement.
(didn’t test this, so possibly some compile-errors/typos)