static factory method in interface class java

Viewed 19296

I was reading Effective java text book. First item is about using static factory methods instead of public constructor. My doubt is that if i am specifying an Interface how can i specify a static factory method in the Interface ? Because java does not support static methods inside interface. The text book specifies about creating a non-instantiable class containing the public static factory methods. But how can those method access the private constructor of the implementation class?

The text book says if you are defining an Interface Type , create a non-instantiable class Types and include the static factory methods in that class. But how can a method defined in the Types class access the private constructor of a concrete implementation of Interface Type

EDIT:- Below sentence is quoted from the text book. Please explain me its meaning

"Interfaces can’t have static methods, so by convention, static factory methods for an interface named Type are put in a noninstantiable class (Item 4) named Types "

EDIT:- taken from Effective Java By Joshua Bloch: Item1 - Static Factory Method

     public interface Foo{ //interface without plural 's' (question 1)
     public void bar();
 }
 public abstract class Foos(){ // abstract factory with plural 's' (question 1)
    public static Foo createFoo(){
        return new MyFoo();
    }
    private class MyFoo implements Foo{ // a non visible implementation (question 2)
       public void bar(){}
    }
 }

My question is that how can the static method createFoo() calls the private constructor of MyFoo

5 Answers

One way to think about this is with the package encapsulation in mind. Consider this Java 9+ code:

public interface Engine {

    void start();

    static Engine getEngine(String type) {
        switch (type) {
            case "combustion":
                return new CombustionEngine();
            case "electric":
                return new ElectricEngine();
            default:
                throw new IllegalArgumentException("Unknown engine type : " + type);
        }
    }
}

class CombustionEngine implements Engine {

    CombustionEngine() {
    }

    @Override
    public void start() {
        // injecting fuel and igniting it to create combustion...
    }
}

class ElectricEngine implements Engine {

    ElectricEngine() {
    }

    @Override
    public void start() {
        // electric current from battery flowing through coil in magnetic field...
    }
}

Note that constructors in implementations are package-private so the caller from a different package can't instantiate implementation directly and should use the factory method.

Having the factory method in the interface

  • has no need for a dedicated EngineFactory class (the traditional implementation of Factory method design pattern)
  • reminds to Program to interface, not implementation

If needed, there is also a way to create implementation instances as singletons, which improves memory footprint :

public interface Engine {

    enum EngineType {

        COMBUSTION,
        ELECTRIC;

        private static EnumMap<EngineType, Engine> MAP = new EnumMap<>(EngineType.class);

        static {
            MAP.put(COMBUSTION, new CombustionEngine());
            MAP.put(ELECTRIC, new ElectricEngine());
        }
    }

    void start();

    static Engine getEngine(EngineType type) {
        return EngineType.MAP.get(type);
    }

}
Related