Java - static factory method and switch statements
factory, java
Solution
Maybe you could create an interface MessageFactory and implementations of it:
public interface MessageFactory {
Message createMessage(Map<String, Object> fields);
Message createMessage(ByteBuffer buffer);
}
public class FirstMessageFactory implements MessageFactory {
public Message createMessage(Map<String, Object> fields){
return new FirstMessage(fields);
}
public Message createMessage(ByteBuffer buffer){
return new FirstMessage(buffer);
}
}
next, a method getFactoryFromId in the same class as the methods above:
public static MessageFactory getMessageFactoryFromId(int uuid){
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessageFactory();
...
default:
// Error
return null;
}
}
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:
public static Message fromMap(int uuid, Map<String, Object> fields) {
getMessageFactoryFromId(uuid).createMessage(fields);
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
getMessageFactoryFromId(uuid).createMessage(buffer);
}
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)
Problem
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.