Singleton
Het concept van Singleton
Singleton verwijst naar een klasse waarvan slechts één instantie kan worden aangemaakt. Typische voorbeelden van singletons zijn stateless objecten of unieke systeemcomponenten. Singleton-klassen zijn echter lastig te testen, tenzij het type wordt gedefinieerd als een interface en de implementatie afzonderlijk wordt gedefinieerd.
Manieren om een Singleton te maken
Een public static lid dat een final veld is
De private constructor wordt slechts één keer aangeroepen bij het initialiseren van de Elvis-instantie, wat garandeert dat er slechts één instantie in het hele systeem is. Het is echter mogelijk om de private constructor aan te roepen met AccessibleObject.setAccessible(), maar deze manipulatie met reflectie kan worden voorkomen door een exception te gooien wanneer een tweede object wordt gemaakt.
- Voordelen
- Het is duidelijk uit de API dat de klasse een singleton is.
- Concise.
Een statische fabrieksmethode leveren die public static is
Ook deze methode garandeert dat er slechts één instantie in het hele systeem is, behalve wanneer er manipulatie met reflectie plaatsvindt. Het enige verschil is dat het veld private is en de retourwaarde van het object wordt geleverd via een statische fabrieksmethode.
- Voordelen
- De singleton kan worden gewijzigd zonder de API te wijzigen.
- Bijvoorbeeld, de statische fabrieksmethode kan worden gewijzigd om voor elke thread een andere instantie terug te geven.
- Het kan indien nodig worden gewijzigd in een generieke singleton fabrieksmethode.
- De methode-referentie van de statische fabrieksmethode kan worden gebruikt als provider.
- Bijvoorbeeld, in plaats van Elvis::getInstance kan Supplier<Elvis> worden gebruikt.
- De singleton kan worden gewijzigd zonder de API te wijzigen.
Als je de bovenstaande voordelen niet nodig hebt, is het beter om de eerste methode te gebruiken.
Een enum-type gebruiken
De meest wenselijke methode is het gebruik van een enum-type. Deze methode is veiliger dan de bovenstaande twee methoden tegen reflectie-aanvallen en de code is netter. Bovendien, zoals hieronder wordt uitgelegd, hebben de bovenstaande twee methoden het nadeel dat er extra code moet worden toegevoegd bij serialisatie.
Houd er echter rekening mee dat hoewel de singleton die je wilt creëren een interface kan erven, deze geen klasse kan erven.
Waarop te letten bij het serialiseren van een singleton-klasse
Als je een singleton-klasse wilt serialiseren die is gemaakt met de eerste of tweede methode hierboven, moet je, naast het implementeren van Serializable, alle instance-velden declareren als transient en de readResolve()-methode overschrijven en deze leveren.
Bronnen
- Effectieve Java
- https://catsbi.oopy.io/d7f3a636-b613-453b-91c7-655d71fda2b1
Reacties0