我的代码中需要一个单例。我用Java实现它,它运行良好。我这样做的原因是为了确保在多个环境中,这个类只有一个实例。
但是现在我想用Unit测试在本地测试我的Singleton对象。出于这个原因,我需要模拟这个Singleton的另一个实例(来自另一个设备的对象)。那么有可能第二次实例化Singleton用于测试目的还是我必须嘲笑它?
我不确定,但我认为可以使用不同的类加载器吗?
答案 0 :(得分:17)
传统上,Singleton创建自己的实例,并且只创建一次。在这种情况下,无法创建第二个实例。
如果使用依赖注入,则可以让框架为您创建单例。单例不会防止其他实例(即它具有公共构造函数),但依赖注入框架仅实例化一个实例。在这种情况下,您可以创建更多用于测试的实例,并且您的对象不会被单例代码混乱。
答案 1 :(得分:16)
Singleton的观点是你只能实例化一次。
答案 2 :(得分:9)
您可以使用反射调用单例类的私有构造函数来创建类的新实例。
class MySingleton {
private MySingleton() {
}
}
class Test {
public void test() throws Exception {
Constructor<MySingleton> constructor = MySingleton.class.getConstructor();
constructor.setAccessible(true);
MySingleton otherSingleton = constructor.newInstance();
}
}
答案 3 :(得分:6)
根据定义,单身只能实例化一次。但是,您的单元测试需要两个单例这一事实强烈表明您的对象不应该是一个单独的,并且您应该重新考虑单例设计。< / p>
答案 4 :(得分:2)
我觉得有必要发布一系列有关Singletons如何破坏可测性并且设计选择不佳的文章:
简短摘要:将类的逻辑与实例化方式相结合,使得代码难以测试,应该避免使用。
答案 5 :(得分:2)
首先,为什么需要创建一个新的单例来运行单元测试?单元测试不应与正常应用程序同时运行,因此您应该能够访问原始单例而无需修改它。
是否有特殊原因需要明确的第二单身?
答案 6 :(得分:1)
你可以制作另一个静态方法getInstance2
,如下所示:
class MySingleton
{
private MySingleton(){}
private static MySingleton instance1 = new MySingleton();
private static MySingleton instance2 = new MySingleton();
public static MySingleton getInstance(){ return instance1; }
public static MySingleton getInstance2(){ return instance2; }
}
答案 7 :(得分:0)
Singleton ston=Singleton.getInstance();
将返回单例对象。通过使用&#34; ston&#34;对象,如果我们调用在Singleton类中编写的方法createNewSingleTonInstance()
将给出新实例。
public class Singleton {
private String userName;
private String Password;
private static Singleton firstInstance=null;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(firstInstance==null){
firstInstance=new Singleton();
firstInstance.setUserName("Prathap");
firstInstance.setPassword("Mandya");
}
return firstInstance;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setPassword(String password) {
Password = password;
}
public String getPassword() {
return Password;
}
public Singleton createNewSingleTonInstance(){
Singleton s=new Singleton();
s.setUserName("ASDF");
s.setPassword("QWER");
return s;
}
}
答案 8 :(得分:0)
您可以在地图上保留一个键并使用键
填充实例public class MultiSingleton {
/**** Non-static Global Variables ***/
String status = "";
private BaseSmartCard bsc;
/***********************************/
private static Object lockObject = new Object();
private String serialNo;
private static Map<String, MultiSingleton> mappedObjects = new TreeMap<String, MultiSingleton>();
protected MultiSingleton() {
}
public static MultiSingleton getInstance(String serialNo,long slotNo){
if (mappedObjects.isEmpty() || !mappedObjects.containsKey(serialNo)) {
MultiSingleton instance = new MultiSingleton();
instance.setSerialNo(serialNo);
mappedObjects.put(serialNo, instance);
return instance;
} else if (mappedObjects.containsKey(serialNo)) {
return mappedObjects.get(serialNo);
}else {
return null;
}
}