简体   繁体   中英

Java - Implementation of a service provider

I've the following "pattern" (not really a truly recognized DP but I tend to use it on my solutions a lot) in C# whose aim is to have a central point of object implementation providing based on interfaces (some sort of Factory).

It is accessed as a singleton and users request the implementation of a given interface and are returned the appropriate implementation.

My goal is to to migrate it to Java. I've two prototype solutions but I'm not quite happy with the results since on one of them (the more powerful & complex) I had to put a lot of abstractions on top of the instantiation mechanisms due to Java's generics limitations and the other albeit simpler is also much less powerful (it can't even take advantage of generics - which could be hany in my usage situation).

I'd like to use it in Java the following way to register new implementations:

ServiceFactory.getInstance().addService(IMyInterface.class, new MyImplementation());

(Where MyImplementations implements IMyInterface).

Follows the original C# version and the two Java versions:

C# Code

public class ObjectProvider<ObjectType, BaseObjectType> : IObjectProvider<BaseObjectType>
   where ObjectType : BaseObjectType, new()
{

  public BaseObjectType ObjectInstance
  {
    get { return (BaseObjectType)new ObjectType(); }
  }
}

public class ServiceManager
{
  private static Dictionary<Type, object> _providersList = null;
  private static object _listLocker = new object();

  private ServiceManager() { }

  private static void InicializeProvidersList()
  {
    _providersList = new Dictionary<Type, object>();

    _providersList.Add(typeof(IMyType), new ObjectProvider<MyImplementation, IMyType>());
       ...
   }

   private static Dictionary<Type, object> ProvidersList
   {
     get
        {
            lock (_listLocker)
            {
                if (_providersList == null)
                    InicializeProvidersList();
                return _providersList;
            }
        }
    }

    public static BusinessType GetBusinessClass<BusinessType>()
    {
        Dictionary<Type, object> list = ProvidersList;
        Type pretendedType = typeof(BusinessType);
        if (!list.ContainsKey(pretendedType))
            return default(BusinessType);
        IObjectProvider<BusinessType> provider = list[pretendedType] as  IObjectProvider<BusinessType>;
        return provider.ObjectInstance;
    }
}

Java (More Powerful Solution) Code

public interface IInstantiator 
{
  <BaseObjectType> BaseObjectType getInstance(Object... args);
  void setCacheable(boolean value);
}

public abstract class BaseInstantiator <BaseObjectType, ObjectType extends BaseObjectType>  implements IInstantiator
{
   protected Class<ObjectType> objectType; 
   protected boolean isCacheable = true;
   protected BaseObjectType cache;

   public BaseInstantiator(Class<ObjectType> objectType)
   {
     this.objectType = objectType;
   }

   public void setCacheable(boolean value)
   {
     this.isCacheable = value;
   }

   @SuppressWarnings("unchecked")
   public final BaseObjectType getInstance(Object... args)
   {
     if(isCacheable && cache != null)
     {
       return cache;
     }
     else
     {
        BaseObjectType objectType = createInstance(args);

        if(isCacheable)
        {
          cache = objectType;
        }

        return objectType;
     }
  }

  protected abstract BaseObjectType createInstance(Object... args);
}

public class Instantiator <BaseObjectType, ObjectType extends BaseObjectType> extends      BaseInstantiator <BaseObjectType, ObjectType> 
{

  public Instantiator(Class<ObjectType> ot)
  {
    super(ot);
  }

  @Override
  protected BaseObjectType createInstance(Object... args)
  {
     try 
     {
       return objectType.newInstance();
     }
     catch (InstantiationException e) 
     {
        e.printStackTrace();
     }
     catch (IllegalAccessException e) 
     {
        e.printStackTrace();
     }

     return null;
  }
}


public class ServiceFactory 
{
  private HashMap<Class, IInstantiator> services;
  private static ServiceFactory instance;

  public <BaseObjectType> void addService(Class<BaseObjectType> baseObjectType, IInstantiator instantiator)
   {
     this.getServices().put(baseObjectType, instantiator);
   }

   @SuppressWarnings("unchecked")
   public <BaseObjectType> BaseObjectType getService(Class<BaseObjectType> baseObjectType, Object... args)
   {

     if(! getServices().containsKey(baseObjectType))
     {
        throw new NoSuchElementException("Unknown service interface!");
     }
     else
     {
       try 
       {
          return (BaseObjectType) getServices().get(baseObjectType).getInstance(args);
       } 
       catch (Exception e) 
       {
          return null;
       }
     }
   }

   private ServiceFactory () { }

   public static synchronized ServiceFactory getInstance()
   {

     if(ServiceFactory.instance == null)
     {
        ServiceFactory.instance = new ServiceFactory();
        populate();
     }

     return ServiceFactory.instance;
   }

   private static void populate()
   {
      //...
   }

   private HashMap<Class, IInstantiator> getServices() 
   {

     if(this.services == null)
     {
       this.services = new HashMap<Class, IInstantiator>();
     }

     return this.services;
   }
}

Java (More Simple and Less Powerful Solution)

@SuppressWarnings("rawtypes")
public class ManagerFactory
{
  private Map<Class, Object> managers;

  private ManagerFactory()
  {
    populateFactory();
  }

  private static class SingletonHolder
  {
    public static final ManagerFactory INSTANCE = new ManagerFactory();
  }

  public static ManagerFactory getInstance()
  {
    return SingletonHolder.INSTANCE;
  }

  private void populateFactory()
  {
    this.managers = new HashMap<Class, Object>();

    this.managers.put(ITaskManager.class, new TaskManager());
  }

  public Object getManager(Class interfaceClass)
  {
    if(this.managers.containsKey(interfaceClass))
      return this.managers.get(interfaceClass);
    else 
      return null;
  }
}

Can anyone offer some help on this one?

Thanks in advance!

This is usually known as the Service Locator pattern .

I would recommend a pre-built solution such as robo-guice .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM