我的spaghetti monster使用来自几个不同SOAP服务的XML,并且每个服务的URL都硬编码到应用程序中。我正在撤消此硬编码,并将URL存储在属性文件中。
在阅读属性文件方面,我想在Singleton中包含可以根据需要引用的逻辑。
改变这个:
accountLookupURL ="http://prodServer:8080/accountLookupService";
对此:
accountLookupURL =urlLister.getURL("accountLookup");
Singleton将包含在urlLister中。
我倾向于回避单身人士模式,只是因为我以前不必使用它。我在正确的轨道上吗?
谢谢!
IVR Avenger
答案 0 :(得分:3)
你还没有说明为什么你只需要获取URL的其中一个。如果这只是涉及读取属性文件,我认为你不需要只有一个。在我看来,让两个线程同时读取相同的属性文件根本不是问题。
除非您考虑使用一些只读取属性文件的对象,然后缓存内容以备将来使用。但这是一个Web应用程序,对吧?因此,处理它的方法是在应用程序启动时读取属性,并将它们存储在应用程序上下文中。只有一个应用程序上下文,所以这是你的“唯一”对象。
答案 1 :(得分:2)
作为替代方案,您是否考虑使用类似Apache Commons Configuration(或可能是其他configuration framework)的内容?
答案 2 :(得分:1)
单身人士适合这种情况,但你必须确保你正确地做单身人士。
所以,例如,Bozhno所暗示的不是单身,它是一种令人讨厌的静态混合物,它不是可以模仿的,不易测试,不可注射,并且通常会回来咬你的屁股。
可接受的单例只是你的普通类,有一个值得注意的例外,它本身或某些外部工厂/框架(例如Spring IoC)只能在一个实例中存在。如果您采用第一种方法,则执行类似
的操作private MyUberSingletonClass() {
//..do your constructor stuff, note it's private
}
private static MyUberSingletonClass instance = null;
public static synchronized MyUberSingletonClass instance() {
if (instance == null) {
instance = new MyUberSingletonClass();
}
return instance;
}
public String getUberUsefulStuff(){
return "42";
}
如果你真的觉得不需要工厂,那是可以接受的,并且你的应用程序中没有使用任何IoC容器(不过考虑使用其中的一个好主意)。注意与Bozhno的例子的不同之处:这是一个很好的vanilla类,其中唯一的静态是实例var和返回它的方法。另请注意延迟初始化所需的synchronized关键字。
更新:Pascal在下面的评论中推荐了一篇关于lazy-init单例的更好方法的非常酷的帖子:http://crazybob.org/2007/01/lazy-loading-singletons.html
答案 3 :(得分:1)
基于你的建议,以及我认为我没有像我希望的那样访问这个应用程序的事实(很多都是在编译代码中抽象出来的),这就是我煮熟的解决方案起来。当然,这是一个存根,需要通过更好的异常处理等来充实。
public class WebServiceURLs {
private static class WebServiceURLsHolder
{
public static WebServiceURLs webServiceURLs = new WebServiceURLs();
}
private Properties webServiceURLs;
public WebServiceURLs()
{
try
{
Properties newURLProperties = new Properties();
InputStreamReader inputStream = new InputStreamReader(
FileLoader.class.getClassLoader().getResourceAsStream("../../config/URLs.properties") );
newURLProperties.load(inputStream);
webServiceURLs =newURLProperties;
}
catch (Exception e)
{
webServiceURLs =null;
}
}
public String getURLFromKey(String urlKey)
{
if (webServiceURLs==null)
return null;
else
return webServiceURLs.getProperty(urlKey);
}
public static WebServiceURLs getInstance()
{
return WebServiceURLsHolder.webServiceURLs;
}
}
public class WebServiceURLs {
private static class WebServiceURLsHolder
{
public static WebServiceURLs webServiceURLs = new WebServiceURLs();
}
private Properties webServiceURLs;
public WebServiceURLs()
{
try
{
Properties newURLProperties = new Properties();
InputStreamReader inputStream = new InputStreamReader(
FileLoader.class.getClassLoader().getResourceAsStream("../../config/URLs.properties") );
newURLProperties.load(inputStream);
webServiceURLs =newURLProperties;
}
catch (Exception e)
{
webServiceURLs =null;
}
}
public String getURLFromKey(String urlKey)
{
if (webServiceURLs==null)
return null;
else
return webServiceURLs.getProperty(urlKey);
}
public static WebServiceURLs getInstance()
{
return WebServiceURLsHolder.webServiceURLs;
}
}
这是我的“第一个”单身人士吗?
谢谢,
IVR Avenger
答案 4 :(得分:0)
重申显而易见的是,当所有客户端代码都与该类的单个实例通信时,将使用Singleton。因此,使用Singleton IFF,您确定不希望一次加载多个属性文件。就个人而言,我希望能够拥有该功能(加载多个属性文件)。
答案 5 :(得分:0)
单身人士是可变的静力因而是邪恶的。 (假设“单身人士”的定义相当有用。
任何使用静态(传递关系)的代码都假设几乎所有其他东西(在这种情况下,Web服务器和互联网)。可变静力学是糟糕的设计,糟糕的设计使许多方面变得腐烂(依赖性,可理解性,测试性,安全性等)。
作为一个例子,阻止在沙盒中使用JUnit 3的后期版本的唯一方法是在一个静态初始化器中加载配置文件。如果它使用了来自Above的参数化,则没有问题。