Reputation: 123
I'm reading the book Effective Java and Joshua Bloch, in chapter 2, said:
A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
I don't understand how to use this concept in practice?
Can someone give me an example?
Upvotes: 2
Views: 1464
Reputation: 11961
1. Hiding from the client (better encapsulation) of object creation
Here's an example of a so-called "Simple Factory" (a.k.a. parametrized factory):
public class UserFactory {
public static User newUser(UserEnum type){
switch (type){
case ADMIN: return new Admin();
case STAFF: return new StaffMember();
case CLIENT: return new Client();
default:
throw new IllegalArgumentException("Unsupported user. You input: " + type);
}
}
}
The point of encapsulating object creation into a static factory is that the users don't know (and don't care) how an object gets created:
// client code - give me an admin object,
// don't care about the inner details of how it gets constructed
User admin = UserFactory.newUser(ADMIN);
2. Flexibility to swap out implementations without breaking client code
Consider this static factory method:
// swap out with LinkedList later if you like,
// it won't break the 100 places that invoke this method
public static List<String> getMyList(){
return new ArrayList<>();
}
Don't like any of the standard list implementations and you create your own some time later?
public class MyMuchBetterList<E> extends AbstractList<E> implements List<E> {
// implementation
}
No problem, you can still swap inside the static factory without affecting those using getMyList:
public static List<String> getMyList(){
return new MyMuchBetterList<>(); // compiles and works, subtype of list
}
Upvotes: 6
Reputation: 51102
Consider for example that you want to write your own option type. You could have an interface MyOption
with two implementing classes, Present
and Absent
. Then you might wish to have a static factory method to convert a possibly-null value into a MyOption
object. It might look like this:
public static <T> MyOption<T> ofNullable(T value) {
if(value == null) {
return new Absent<>();
} else {
return new Present<>(value);
}
}
Note that the static factory method MyOption.ofNullable(value)
returns a different class of object depending on the value of the argument. It would be impossible to write a constructor such that new MyOption<>(value)
had the same behaviour.
Upvotes: 2