Как создать экземпляр Синглтона несколько раз?
Мне нужен синглтон в моем коде. Я реализовал его на Java, и он работает хорошо. Причина, по которой я это сделал, заключается в том, что в среде mulitple существует только один экземпляр этого класса.
но теперь я хочу проверить мой одноэлементный объект локально с помощью модульного теста. По этой причине мне нужно смоделировать другой экземпляр этого Синглтона (объект, который будет с другого устройства). Так есть ли возможность создать экземпляр Синглтона во второй раз для целей тестирования или у меня есть глумиться то?
Я не уверен, но я думаю, что это может быть возможно с помощью другого загрузчика классов?
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();
}
}
традиционно Синглтон создает свой собственный экземпляр, и он создает его только один раз. В этом случае невозможно создать второй экземпляр.
Если вы используете инъекцию зависимостей, вы можете позволить структуре создать синглтон для вас. Синглтон не защищает от других экземпляров (т. е. он имеет открытый конструктор), но среда внедрения зависимостей создает только один экземпляр. В этом случае можно создать больше экземпляров для тестирования, а объект-нет загроможденный одноэлементным кодом.
синглтон по определению может быть создан только один раз. Однако тот факт, что ваш модульный тест требует два singletons является сильным признаком того, что ваш объект Не стоит одноэлементный, и что вы должны переосмыслить дизайн singleton.
Я чувствую себя вынужденным опубликовать эту серию статей о том, как Синглеты разрушают тестируемость и являются плохими вариантами дизайна:
краткое резюме: объединение логики для того, что класс делает с тем, как он создается, делает код уродливым для тестирования и должен быть избежавший.
во-первых, почему вам нужно создать новый синглтон для запуска модульного теста? Модульный тест не должен выполняться одновременно с обычным приложением, поэтому вы должны иметь доступ к исходному одноэлементному элементу, не опасаясь его изменения..
есть ли конкретная причина, по которой вам нужен явный второй синглтон?
вы можете просто сделать другой статический метод 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; }
}
Singleton ston=Singleton.getInstance();
вернет объект singleton. Используя объект "ston", если мы вызываем метод 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;
}
}
вы можете сохранить ключ на карте и заполнить экземпляр ключом
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;
}
}