Two similar factory classes to instantiate services I'm working on building a library to help you bootstrap the development of a Java API. The premise is, you can have your controllers implement interfaces like IGetController&lt;SomeEntity&gt; or IListController&lt;SomeEntity&gt;.  These interfaces have default methods to implement their endpoint, and use a service factory to get the appropriate service to do the bulk of the work.  These services are also interfaces, and have default methods which get a repository (by calling getRepository on the IBaseService they extend).  There's a lot of "magic" going on here to inspect the genericInterfaces on the class, and then getting the type arguments to determine what entity we're working with.

The problem I'm having is consolidating my factories.  Take a look at these two factory classes:

GetServiceFactory:

package apibuilder.service.factory;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import apibuilder.entity.BaseEntity;
import apibuilder.service.IGetService;

public class GetServiceFactory {
    private static final Map&lt;Type, IGetService&lt;? extends BaseEntity&gt;&gt;
            registrationMap = new HashMap&lt;&gt;();

    public static &lt;T extends BaseEntity&gt; IGetService&lt;T&gt; getService(final Type entityType) {
        if (registrationMap.containsKey(entityType)) {
            //noinspection unchecked
            return (IGetService&lt;T&gt;) registrationMap.get(entityType);
        }
        return null;
    }

    public static &lt;T extends BaseEntity&gt; void registerServices(final IGetService&lt;T&gt;[] services) {
        for (IGetService&lt;T&gt; service : services) {
            Type entityType = ((ParameterizedType) service.getClass().getGenericInterfaces()[0])
                    .getActualTypeArguments()[0];
            registrationMap.put(entityType, service);
        }
    }
}


ListServiceFactory:

package apibuilder.service.factory;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import apibuilder.entity.BaseEntity;
import apibuilder.service.IListService;

public class ListServiceFactory {
    private static final Map&lt;Type, IListService&lt;? extends BaseEntity&gt;&gt;
            registrationMap = new HashMap&lt;&gt;();

    public static &lt;T extends BaseEntity&gt; IListService&lt;T&gt; getService(final Type entityType) {
        if (registrationMap.containsKey(entityType)) {
            //noinspection unchecked
            return (IListService&lt;T&gt;) registrationMap.get(entityType);
        }
        return null;
    }

    public static &lt;T extends BaseEntity&gt; void registerServices(final IListService&lt;T&gt;[] services) {
        for (IListService&lt;T&gt; service : services) {
            Type entityType = ((ParameterizedType) service.getClass().getGenericInterfaces()[0])
                    .getActualTypeArguments()[0];
            registrationMap.put(entityType, service);
        }
    }
}


As you can see, they're nearly identical.  They create a map to get the proper service per entity, and then have methods to build the map, and get a service from the map.  I feel like these can be consolidated into some sort of BaseServiceFactory, but I'm having a hard time actually pulling it off.
Problem is that you prefer static methods. This way you effectively throw away benefits of polymorphism.

Also, when ever you find duplicated code you should carefully think if it might belong into a class of its own. 

If you could open your mint to an OO approach you could move common behavior into a (non static) utility class and inject that common behavior into the concrete Factories. Or you go the usual OO way to create an abstract factory having the common code and have the concrete factories inheriting from it.




  but why do static methods throw away polymorphism benefits?  – Thufir 


Static method imply early binding. All accessors to a method are known at compile time of the method implementation. Also all implementors of a static method are known at compile time of the accessors. You cannot provide a new behavior of a method unless you compile the accessors needing this new behavior.

class A {
  static void method(){
     System.out.println("static method in A");
  }
}


class B extends A {
  static void method(){
     System.out.println("static method B");
  }
}

class  C {
  static void main(String[] args){
     A.method(); // outputs "static method in A"
     B.method(); // outputs "static method in B"
     A[] a = {new A(), new B()};
     a[0].method();  // outputs "static method in A"
     a[1].method();  // outputs "static method in A" although instance is f type `B` 
  }
}



  And, is polymorphism really so beneficial? – Thufir 


Polymorphism is no value as such.

But if you doubt the value of polymorphism in general you might rather use a programing language that does not bother you with such  gratuitous  concepts...