创建和管理Java中可由不同用户访问的类的唯一实例

时间:2015-04-02 02:21:09

标签: java oop design-patterns static-factory

我有一个编程问题,我想知道它是否可以使用Java设计技术解决。我有班级服务,我有班级客户。客户端请求服务,如果它尚未存在,则将创建它(即新服务对象)。如果已创建服务(即由不同的客户端或甚至同一客户端),则Service类将不会创建新对象。相反,可以将客户端添加到服务(如果尚未添加)。 Service类的其他字段和方法将应用于同一服务的客户端。

public class Service {

  private String service;
  private ArrayList<Integer> clients;
  //.... other field    

  public Service (String s){
    this.service = s;
    clients = new ArrayList<>;  
  } 

  public void addClient(int c){
    clients.add(c);
  }



  //..other methods

}

public class Client {

  private int clientID;
  private ArrayList<String> services;

  public Client(int id){
    clientID = id;
    services = new ArrayList<>;
  }

  public void addService(String s){
    services.add(s);
  }

  public void requestService() {
    for(int i=0; i<services.size();i++)
        Service s = new Service(services.get(i));
  } 

}

上述方法的问题在于,不同客户端将创建具有相同服务的新服务对象。

我正在阅读静态工厂。就我的研究而言:

public class Service(){

private Service(){
}

  public static Service createService(String service){
     if (/*service doesn't exist*/)
       return new Serivce();
     else
       return null;
   }
//....
}

以上代码会阻止创建新的对象实例。但是,如果服务已存在并因此返回null,则新客户端无法加入(或使用)该特定服务。

1 个答案:

答案 0 :(得分:0)

我认为你正在寻找的是典型的懒惰单身人士模式。看看here,关注Initialization-on-demand holder idiom这是我认为最好的方法,因为它是100%线程安全的。

public class Service {

  // Private constructor. Prevents instantiation from other classes.
  private Service() {
  }

  // Initializes Service singleton.
  private static class SingletonHolder {

    private static final Service INSTANCE = new Service();
  }

  // gets the one and only instance of Service
  public static Service getInstance() {
    return SingletonHolder.INSTANCE;
  }
}

修改

查看静态工厂代码,看起来您实际上正在寻找一个服务容器,该容器为您传递的特定密钥(服务名称或服务类以提供更好的类型安全性)提供唯一的服务实例。在下面,您将找到一个非常基本的非线程安全实现,使用类作为键。如果你谷歌四处寻找线程安全的多线程,那么还有很多其他更好的线程安全实现。或类似的。但是如果你现在在绿地上,我强烈建议使用dependency injection framework,除了带来许多其他好处之外,它已经为你完成了整个工作。我特别喜欢谷歌的Guice,但决定使用什么取决于你的项目。如果您需要帮助做出决定,我建议发布一个新的主题,其中包含项目的详细信息以及您需要此服务容器的内容。

public class ServiceContainer {

  private final Map<Class<?>, Service> map = new HashMap<>();

  // Private constructor. Prevents instantiation from other classes.
  private ServiceContainer() {
  }

  // ServiceContainer singleton.
  private static class SingletonHolder {

    private static final ServiceContainer INSTANCE = new ServiceContainer();
  }

  // gets the one and only instance for a particular Service class
  @SuppressWarnings("unchecked")
  public static <T extends Service> T getInstance(final Class<T> serviceClass) {
    // init service if not initialized yet
    if (!SingletonHolder.INSTANCE.map.containsKey(serviceClass)) {
      SingletonHolder.INSTANCE.map.put(serviceClass, createService(serviceClass));
    }
    return (T)SingletonHolder.INSTANCE.map.get(serviceClass);
  }

  private static <T extends Service> T createService(final Class<T> serviceClass) {
    try {
      return serviceClass.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      // please handle this exception properly
      throw new RuntimeException(e);
    }
  }
}