Wie kann ein Singleton mehrere Male instanziiert werden?

Ich brauche ein Singleton in meinem Code. Ich habe es in Java implementiert und es funktioniert gut. Der Grund, warum ich es getan habe, ist sicherzustellen, dass es in einer multiplen Umgebung nur eine Instanz dieser class gibt.

Aber jetzt möchte ich mein Singleton-Objekt lokal mit einem Unit-Test testen. Aus diesem Grund muss ich eine andere Instanz dieses Singleton simulieren (das Objekt, das von einem anderen Gerät kommen würde). Gibt es also eine Möglichkeit, ein Singleton ein zweites Mal zu Testzwecken zu instantiieren oder muss ich es verspotten?

Ich bin mir nicht sicher, aber ich denke, es könnte möglich sein, mit einem anderen classnlader?

Sie können den privaten Konstruktor Ihrer Singleton-class mithilfe von Reflection aufrufen, um eine neue Instanz der class zu erstellen.

class MySingleton { private MySingleton() { } } class Test { public void test() throws Exception { Constructor constructor = MySingleton.class.getConstructor(); constructor.setAccessible(true); MySingleton otherSingleton = constructor.newInstance(); } } 

Traditionell erstellt ein Singleton seine eigene Instanz und erstellt sie nur einmal. In diesem Fall ist es nicht möglich, eine zweite Instanz anzulegen.

Wenn Sie Dependency Injection verwenden, können Sie das Framework den Singleton für Sie erstellen lassen. Das Singleton schützt nicht vor anderen Instanzen (dh es hat einen öffentlichen Konstruktor), aber das Dependency-Injection-Framework instanziiert nur eine Instanz. In diesem Fall können Sie weitere Instanzen zum Testen erstellen, und Ihr Objekt ist nicht mit Singleton-Code überladen.

Der Punkt eines Singleton ist, dass Sie es nur einmal instanziieren können.

Ein Singleton kann per Definition nur einmal instanziiert werden. Die Tatsache, dass Ihr Komponententest zwei Singletons erfordert, ist jedoch ein starkes Anzeichen dafür, dass Ihr Objekt nicht wirklich ein Singleton sein sollte und dass Sie das Singleton-Design überdenken sollten.

Ich fühle mich gezwungen, diese Artikelserie darüber zu veröffentlichen, wie Singletons Testbarkeit zerstören und schlechte Design-Entscheidungen sind:

  • Singletons sind pathologische Lügner
  • Wo sind alle Singletons geblieben?
  • Grundursache von Singletons

Kurze Zusammenfassung: Das Kombinieren von Logik für das, was eine class tut, mit ihrer Instanziierung macht Code, der hässlich zu testen ist, und sollte vermieden werden.

Erstens, warum müssen Sie einen neuen Singleton erstellen, um einen Komponententest auszuführen? Ein Komponententest sollte nicht gleichzeitig mit der normalen Anwendung ausgeführt werden, daher sollten Sie in der Lage sein, auf den ursprünglichen Singleton zuzugreifen, ohne befürchten zu müssen, ihn zu modifizieren.

Gibt es einen bestimmten Grund, warum Sie einen expliziten zweiten Singleton benötigen?

Sie könnten einfach eine andere statische Methode getInstance2 , die wie getInstance2 aussieht:

 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(); wird Singleton-Objekt zurückgeben. Wenn wir das “ston” -Objekt verwenden, wird die Methode createNewSingleTonInstance() die in der Singleton-class geschrieben ist, eine neue Instanz erhalten.

 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; } } 

Sie können einen Schlüssel auf einer Karte behalten und die Instanz mit dem Schlüssel füllen

 public class MultiSingleton { /**** Non-static Global Variables ***/ String status = ""; private BaseSmartCard bsc; /***********************************/ private static Object lockObject = new Object(); private String serialNo; private static Map mappedObjects = new TreeMap(); 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; } }