通过配置文件初始化单例是否合适?
我注意到单例的构造函数不应该有任何参数,原因是如果您需要使用参数来配置对象,那么很可能不应该是单例。这句话似乎很有名,但确实有一些役例是特殊的:
例如,我们设计了一个简单的分布式系统来处理大量的用户查询:
显然,我们可以将“中央服务器”设计为“单例”,具体如下:
但是中央服务器需要一些配置,例如:
如何通过这些属性初始化中心服务器?
我目前的解决方案:
Configuration的类。因此,中央服务器的当前构造函数如下:
class CentralServer extends Server implements Runnable, ....... {
....
....
private static CentralServer _instance;
private CentralServer () {
super();
....
serverName = Configuration.getCentralServerName();
description = Configuration.getCentralServerDescription();
Configuration.initCentralServerPortNumIpMap(portNumIpMap);
Configuration.initCentralServerSubServersList(subServersList);
sizeBlockingQueue = Configuration.initCentralServerBlockingQueueSize();
....
}
public CentralServer getInstance() {
if (_instance == null) {
_instance = new CentralServer();
}
return _instance;
}
....
....
}配置类,将读取和分析配置文件,以获取配置信息。
我的问题是:
发布于 2014-08-30 22:53:34
不幸的是,您对Singelton的实现是错误的!!仅仅因为它不是线程安全的。
public CentralServer getInstance() {
if (_instance == null) { // race condition possible here
_instance = new CentralServer();
}
return _instance;
}两个线程可能进入这个关键部分并将_instance==null计算为true,并且将创建两个不同的实例。您可以简单地静态地实例化实例。
private final static CentralServer INSTANCE = new CentralServer();
public static CentralServer getInstance() {
return INSTANCE;
}然而,实现单However的最佳方法是使用enums
public enum CentralServer { // the best way to implement singletons, due to the author of Effective Java
INSTANCE;
private CentralServer() {
}
}这使您可以免费序列化。然而,我认为你根本不需要一个单子,单子通常是反模式的。看看这个。
在您的代码中,CentralServer对Configuration有很高的依赖性,我认为这不是一件好事,您应该将配置视为依赖关系
class CentralServer{
private final Configuration serverConf;
private CentralServer(Configuration serverConf){ // inject configuration
this.serverConf = serverConf;
}
public static CentralServer createCentralServer(Configuration serverConf){ // static factory perhaps
return new CentralServer(serverConf);
}
}这将为您提供更改或模拟配置的更大灵活性。我认为工厂模式在这里更合适。
发布于 2014-08-30 22:50:12
初始化这样的单身人士是否合适,如果不合适,请给出更合适的方法:
这不是一种合适的方法,因为实现还不是线程安全,而且可以破坏f.e。通过反射。您应该考虑阅读有关此主题的约书亚·布洛赫的有效Java。
最好是创建一个enum,因为这种方法对于以后的更改更加灵活,具有threadsafe实例化,并且不可中断。
编辑:示例 .
我还需要配置所有的子服务器,所以似乎配置类太重了,应该将大配置类划分为两个子类吗?CentralConfiguration类和SubConfiguration类?
为了进行配置,通常会有一个config.xml文件或一个config.properties文件来读取重要的预配置。在创建实例之后,您应该从这样的文件中提取信息,并在关闭时写出必要的更改。但和往常一样,很多方式都通向罗马。
发布于 2014-08-30 22:55:09
在初始化单例时使用外部资源是完全可以接受的。Singleton模式的一个常见用户是记录器,它们几乎总是通过外部数据文件配置的。
它确实使初始化变得更加复杂,但要使完全安全的单例访问外部资源(如配置文件)并不是不可能的。如果它们的配置需要数据库访问,它们甚至可以使用其他的单件,例如连接池。
这个问题的其他答案正确地处理了单例初始化的实际问题。
https://stackoverflow.com/questions/25587264
复制相似问题