我有一个编程问题,我想知道它是否可以使用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,则新客户端无法加入(或使用)该特定服务。
答案 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);
}
}
}