CodeGym /Java Blog /Willekeurig /Patronen en Singleton in Java
John Squirrels
Niveau 41
San Francisco

Patronen en Singleton in Java

Gepubliceerd in de groep Willekeurig
Dit artikel is bedoeld voor iedereen die voor het eerst in aanraking komt met het concept van ontwerppatronen, de term singleton heeft gehoord of op de een of andere manier het singleton-patroon heeft geïmplementeerd, maar niet begreep wat er gebeurde. Welkom! CodeGym-studenten komen voor het eerst ontwerppatronen tegen op niveau 15, wanneer de kapitein hen onverwachts vraagt ​​om hun begrip te "versterken" door het Java Singleton-patroon met luie implementatie te implementeren. Studenten die voor het eerst over het singleton- patroon horen, hebben meteen veel vragen: wat is in vredesnaam een ​​ontwerppatroon? Waarom hebben we het nodig? Wat is een eenling ? En tot slot, wat is luie implementatie? Laten we deze vragen in volgorde beantwoorden.

Wat is in hemelsnaam een ​​ontwerppatroon?

Ik geloof dat een beetje geschiedenis nodig is om deze vraag met het beste begrip te beantwoorden. Er zijn vier beroemde programmeerauteurs (Erich Gamma, John Vlissides, Ralph Johnson en Richard Helm) die met een interessant idee kwamen. Ze merkten dat ze bij het ontwikkelen van software vaak ongeveer dezelfde problemen moesten oplossen en code op dezelfde manier moesten schrijven. Daarom besloten ze typische patronen te beschrijven die vaak moeten worden gebruikt bij objectgeoriënteerd programmeren. Hun boek verscheen in 1994 onder de titel Design Patterns: Elements of Reusable Object-Oriented Software. De naam van het boek bleek te lang en mensen begonnen het simpelweg het boek van de Bende van Vier te noemen. De eerste editie omvatte 23 patronen. Daarna werden tientallen andere patronen ontdekt.
Een ontwerppatroon is een gestandaardiseerde oplossing voor een veelvoorkomend probleem.
En het singleton- patroon is er slechts een van.

Waarom hebben we ontwerppatronen nodig?

Je kunt programmeren zonder patronen te kennen: op niveau 15 heb je tenslotte al honderden miniprogramma's op CodeGym geschreven zonder zelfs maar te weten dat ze bestaan. Dit suggereert dat ontwerppatronen een soort hulpmiddel zijn waarvan het gebruik de meester onderscheidt van de amateur: ontwerppatronen beschrijven hoe een typisch probleem op de juiste manier kan worden opgelost. Dit betekent dat het kennen van patronen je tijd bespaart. In die zin zijn ze vergelijkbaar met algoritmen. U kunt bijvoorbeeld uw eigen sorteeralgoritme maken met blackjack en getallenen besteed er veel tijd aan, of u kunt er een implementeren die al lang wordt begrepen en beschreven. Hetzelfde geldt voor ontwerppatronen. Bovendien wordt code met ontwerppatronen meer standaard, en als u het juiste patroon gebruikt, is de kans kleiner dat u fouten maakt, omdat de veelvoorkomende valkuilen van het patroon lang geleden zijn geïdentificeerd en geëlimineerd. Bovendien helpt kennis van patronen programmeurs elkaar beter te begrijpen. Je kunt gewoon de naam van een patroon zeggen in plaats van een uitgebreide uitleg te geven aan je collega-programmeurs. Samenvattend helpen ontwerppatronen u:
  • niet het wiel opnieuw uitvinden, maar gebruik maken van standaardoplossingen;
  • code standaardiseren;
  • standaardiseren van terminologie;
Om deze sectie af te sluiten, merken we op dat het hele lichaam van ontwerppatronen in drie grote groepen kan worden verdeeld: Patronen en singleton - voor iedereen die ze voor het eerst tegenkomt - 2

Tot slot het singleton-patroon

Singleton is een scheppingspatroon . Dit patroon zorgt ervoor dat er slechts één instantie van een klasse is en biedt een globaal toegangspunt voor dit object. Uit de beschrijving zou duidelijk moeten zijn dat dit patroon in twee gevallen moet worden toegepast:
  1. wanneer uw programma vereist dat er niet meer dan één object van een bepaalde klasse wordt gemaakt. Een computerspel kan bijvoorbeeld een Hero-klasse hebben en slechts één Hero-object dat de enige held in het spel beschrijft.

  2. wanneer u een punt moet bieden voor wereldwijde toegang tot een object. Met andere woorden, u moet het object overal in het programma beschikbaar maken. Helaas is het niet voldoende om simpelweg een globale variabele te maken, aangezien deze niet tegen schrijven is beveiligd: iedereen kan de waarde van de variabele wijzigen, dus het globale toegangspunt van het object kan verloren gaan. Deze eigenschappen van een Singleton zijn bijvoorbeeld nodig wanneer u een object hebt dat met een database werkt en u de database vanuit verschillende delen van het programma moet benaderen. Een Singleton zorgt ervoor dat niemand code schrijft die de eerder gemaakte instantie vervangt.
Dus een Singleton voldeed aan deze twee behoeften: er mag slechts één van een bepaald soort object in het programma zijn en er moet wereldwijde toegang toe zijn. In het voorbeeld op niveau 15 vraagt ​​de kapitein je om dit patroon te implementeren voor de volgende taak:
  1. Zoek een voorbeeld van Singleton met luie initialisatie.

  2. Maak drie singleton-klassen - zon, maan, aarde - in afzonderlijke bestanden volgens hetzelfde principe.

  3. ImplementerenPlaneetinterface in de klassen Zon , Maan en Aarde .

  4. Roep in statisch blok van de klasse Solution dereadKeyFromConsoleAndInitPlanetmethode.

  5. Implementeer dereadKeyFromConsoleAndInitPlanetmethode functionaliteit:

    • 5.1. Lees één String- parameter van de console

    • 5.2. Als de parameter gelijk is aan een van dePlaneetinterface-constanten, maak dan een geschikt thePlanet- object.

Na zorgvuldig de taakvoorwaarden te hebben gelezen, kunnen we duidelijk zien waarom hier een Singleton nodig is. We worden inderdaad gevraagd om een ​​instantie te maken van elk van de volgende klassen: Sun , Moon , Earth . Het is logisch om aan te nemen dat we niet meer dan één Zon/Maan/Aarde zouden moeten creëren. Anders komen we in een absurde situatie terecht, tenzij je natuurlijk jouw versie van Star Wars aan het schrijven bent. Het Singleton- patroon implementeren in Java in drie stappen In Java kan Singleton-gedrag niet worden geïmplementeerd met een gewone constructor, omdat een constructor altijd een nieuw object retourneert. Daarom zijn alle implementaties van Singletonkomt neer op het verbergen van de constructor, het creëren van een openbare statische methode die de levensduur van het singleton-object regelt en het "vernietigen" van alle nieuw verschijnende objecten. Als een Singleton wordt benaderd, moet het een nieuw object maken (als er nog geen bestaat in het programma), of een bestaand object retourneren. Om dit te bereiken:
  1. U moet de klasse een privé statisch veld geven dat een enkel object opslaat:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance; // #1
    }
    
  2. Maak de (standaard) constructor privé. Dit betekent dat het niet toegankelijk is buiten de klasse en geen nieuwe objecten kan retourneren:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance;
    private LazyInitializedSingleton(){} // #2
    } 
    
  3. Declareer een statische aanmaakmethode die zal worden gebruikt om de singleton te krijgen:

    
    public class LazyInitializedSingleton {
        private static LazyInitializedSingleton instance;
            private LazyInitializedSingleton() {}
            public static LazyInitializedSingleton getInstance() { // #3
            if (instance == null) { // If the object has not yet been created
                instance = new LazyInitializedSingleton(); // Create a new object
            }
            return instance; // Return the previously created object
        }
    }
    
Het bovenstaande voorbeeld is wat onhandig, omdat we de constructor simpelweg verbergen en onze eigen methode bieden in plaats van een standaard constructor. Aangezien dit artikel tot doel heeft ervoor te zorgen dat CodeGym-studenten in aanraking komen met dit patroon (en ontwerppatronen in het algemeen), worden de nuances van complexere singleton-implementaties hier niet beschreven. We merken alleen op dat, afhankelijk van de complexiteit van het programma, dit patroon mogelijk verder moet worden verfijnd. In een omgeving met meerdere threads (zie artikelen over threads) kunnen verschillende threads bijvoorbeeld tegelijkertijd toegang hebben tot de singleton-methode en zal de hierboven beschreven code niet meer werken, aangezien elke afzonderlijke thread een instantie van de klasse zou kunnen creëren. Als gevolg hiervan zijn er nog steeds verschillende benaderingen voor het maken van goede thread-safe singletons. Maar dat is een ander verhaal =)

En tot slot... Wat is die luie initialisatie waar de kapitein naar vroeg?

Luie initialisatie wordt ook uitgestelde initialisatie genoemd. Dit is een programmeertruc waarbij een resource-intensieve bewerking (en het maken van een object is een resource-intensieve bewerking) op verzoek wordt uitgevoerd in plaats van van tevoren. Dus wat gebeurt er eigenlijk in onze Singleton Java-code? Met andere woorden, ons object wordt gemaakt op het moment dat het wordt geopend, niet van tevoren. Je moet er niet van uitgaan dat luie initialisatie op de een of andere manier star gebonden is aan het Singleton- patroon. Luie initialisatie wordt ook gebruikt in andere creatieve ontwerppatronen, zoals Proxy en Factory Method, maar dit is ook een ander verhaal =)
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION