Rosicleia Frasson
Rosicleia Frasson

Reputation: 123

Static Factory Methods - return any subtype

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

Answers (2)

Andrejs
Andrejs

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

kaya3
kaya3

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

Related Questions