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?
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
}