1

我有一个编程问题,我想知道它是否可以使用 Java 设计技术来解决。我有班级服务,我有班级客户。客户端请求一个服务,如果它不存在,那么它将被创建(即新的服务对象)。如果服务已创建(即由不同的客户端甚至相同的客户端),则服务类将不会创建新对象。相反,可以将客户端添加到服务中(如果尚未添加)。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,则新客户端无法加入(或使用)该特定服务。

4

1 回答 1

0

我认为您正在寻找的是典型的惰性单例模式。看看这里,重点关注Initialization-on-demand 持有者习惯用法,我认为这是最好的方法,因为它是 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;
  }
}

编辑:

查看您的静态工厂代码,看起来您实际上是在寻找一个服务容器,该容器为您传递的特定键(服务名称或服务类以提高类型安全性)提供一个且唯一的服务实例。下面你会发现一个使用类作为键的非常基本的非线程安全实现。如果您搜索“线程安全多线程”或类似内容,还有很多其他更好的线程安全实现。但是,如果您现在处于绿色领域,我强烈建议您使用依赖注入框架,除了带来许多其他好处之外,它已经为您完成了整个工作。我特别喜欢 Google 的 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);
    }
  }
}
于 2015-07-11T20:39:36.253 回答