The Factory method
The Factory method pattern, as the name implies, provides a way of building multiple instances of different types without knowing precisely how the objects are created. That is, we call an abstract method (that is inherently undefined) on a concrete data type. Quite often, one builds a singleton Factory method implementation and then uses the same method to build other objects as needed.
First, start with an abstract class that defines a generic message.
public abstract class Message {
public abstract String getContent();
public void addDefaultHeaders() {
// Adds default headers
}
public void encrypt() {
// Encrypt the content
}
}
Then provide more specific extensions of the abstract Message
class.
public class JSONMessage extends Message {
@Override
public String getContent() {
return "{JSON:[]}";
}
}
// defined elsewhere
public class TextMessage extends Message {
@Override
public String getContent() {
return "Text";
}
}
The abstract Factory class would instantiate the abstract Message
class.
public abstract class MessageCreator {
public Message getMessage() {
Message msg = createMessage();
msg.addDefaultHeaders();
msg.encrypt();
return msg;
}
// Factory method (implemented by the concrete classes)
// this method can also be defined to set defaults if desired
protected abstract Message createMessage();
}
Then extend the abstract Factory method for all relevant concrete classes.
public class JSONMessageCreator extends MessageCreator {
@Override
public Message createMessage() {
return new JSONMessage();
}
}
// defined elsewhere
public class TextMessageCreator extends MessageCreator {
@Override
public Message createMessage() {
return new TextMessage();
}
}
The client then requests specific instances as follows, passing a new concrete class instance and applying polymorphism in place of MessageCreator
and Message
.
public class Client {
public static void main(String[] args) {
printMessage(new JSONMessageCreator());
printMessage(new TextMessageCreator());
}
public static void printMessage(MessageCreator creator) {
// call an abstract method on an abstract "instance" which works since
// an extension (and definition) is known at run-time
Message msg = creator.getMessage();
System.out.println(msg);
}
}