【问题标题】:Java - Implementation of a service providerJava - 服务提供者的实现
【发布时间】:2012-03-06 11:22:19
【问题描述】:

我在 C# 中有以下“模式”(不是真正公认的 DP,但我倾向于在我的解决方案中经常使用它),其目的是基于接口(某种形式)提供对象实现的中心点工厂)。

它作为单例访问,用户请求给定接口的实现并返回适当的实现。

我的目标是将它迁移到 Java。我有两个原型解决方案,但我对结果不太满意,因为在其中一个(更强大和更复杂)上,由于 Java 的泛型限制,我不得不在实例化机制之上放置很多抽象,而另一个尽管更简单,但功能也没有那么强大(它甚至不能利用泛型——这在我的使用情况下可能很实用)。

我想在 Java 中通过以下方式使用它来注册新的实现:

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

(MyImplementations 实现 IMyInterface)。

沿用原来的 C# 版本和两个 Java 版本:

C# 代码

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(更强大的解决方案)代码

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(更简单但功能更弱的解决方案)

@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;
  }
}

任何人都可以在这方面提供一些帮助吗?

提前致谢!

【问题讨论】:

    标签: java android generics design-patterns provider


    【解决方案1】:

    这通常称为Service Locator pattern

    我会推荐一个预构建的解决方案,例如robo-guice

    【讨论】:

    • 谢谢,拉斯穆斯!我实际上忘了说明我打算在 Android 应用程序中使用它。因此,Spring 可能不是答案。我以前使用过 guice,但没有遵循它,因此必须检查它是否支持 Android。我不知道 Pico,所以我也必须检查一下。
    • @Diesel Heart:那么考虑看看 robo-guice。
    • 是的!非常感谢,拉斯穆斯。回答您后不久,我在 Google 上找到了 RoboGuice。无论如何,你有关于我的服务定位器 Java 实现的任何 cmets(让我们现在将其视为纯粹的学术练习)吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2012-08-07
    相关资源
    最近更新 更多