javastatic-factory

static factory method in interface class java


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


Solution

  • You can define the factory as returning the Interface but internally it creates a concrete class.

    For example:

    public Interface I { }
    
    private class Impl implements I {
    }
    
    I buildI() {
        return new Impl();
    }
    

    The trick is to create the implementations with package private (or even if they are inner classes private) constructors and then only the factory can build them.

    The power of this method is that the factory can build the appropriate implementation depending on the requirements and that all happens invisibly to the user. For example when you create an EnumSet using the factory there are multiple internal implementations depending on how many entries there are in the Enum that the EnumSet is being built for. A super-fast version using bitfields on a long for Enums with less than 64 entries, a slower version for longer enumerations.

    To specify the interface for a factory all you need to do is:

    public interface Factory {
       I buildI();
    }
    

    Now people can call you with setFactory(new FactoryImpl()); you can then call factory.buildI() and their code then returns the concrete implementation.

    You can take this a step further and use Generics:

    public interface GenericFactory<T> {
        T buildInstance();
    }
    

    And then your setFactory becomes:

    public void setFactory(GenericFactory<I> factory);
    

    To create a factory they do:

    public class FactoryImpl implements GenericFactory<I> {
         @override
         I buildInstance() {
            return new impl();
         }
    }
    

    But now you can use that same factory class for absolutely anything that needs a factory, just change the generics requirement.

    The reason it can call the private constructor is very simple - it's declared in the same class!

    Inside one Java file you can create the class with the private constructor. You then define the static method inside the class and even though it is static it still has the privileges required to access the constructor.

    If the factory and implementation are in separate classes then they will be placed in the same package and the method made package private instead of private.