CodeGym /Java blogg /Slumpmässig /Mönster och Singleton i Java
John Squirrels
Nivå
San Francisco

Mönster och Singleton i Java

Publicerad i gruppen
Den här artikeln riktar sig till alla som för första gången stöter på konceptet designmönster, har hört termen singel eller på något sätt implementerat singelmönstret men inte förstått vad som hände. Välkommen! CodeGym-studenter möter designmönster för första gången på nivå 15, när kaptenen oväntat ber dem att "förstärka" sin förståelse genom att implementera Java Singleton-mönstret med lat implementering. Studenter som hör talas om singelmönster för första gången har omedelbart många frågor: vad i hela friden är ett designmönster? Varför behöver vi det? Vad är en singleton ? Och slutligen, vad är lat implementering? Låt oss svara på dessa frågor i ordning.

Vad i hela friden är ett designmönster?

Jag tror att lite historia är för att besvara denna fråga med bästa förståelse. Det finns fyra kända programmeringsförfattare (Erich Gamma, John Vlissides, Ralph Johnson och Richard Helm) som kom på en intressant idé. De märkte att mjukvaruutveckling ofta krävde att de löste ungefär samma problem och skrev kod strukturerad på samma sätt. Så de bestämde sig för att beskriva typiska mönster som ofta behöver användas i objektorienterad programmering. Deras bok publicerades 1994 under titeln Design Patterns: Elements of Reusable Object-Oriented Software. Bokens namn visade sig vara för långt och folk började helt enkelt kalla den boken av Fyragänget. Den första upplagan innehöll 23 mönster. Efteråt upptäcktes dussintals andra mönster.
Ett designmönster är en standardiserad lösning på ett vanligt problem.
Och singelmönstret är bara en av dem.

Varför behöver vi designmönster?

Du kan programmera utan att känna till mönster: trots allt, på nivå 15, har du redan skrivit hundratals miniprogram på CodeGym utan att ens veta att de finns. Detta tyder på att designmönster är ett slags verktyg vars användning skiljer mästaren från amatören: Designmönster beskriver hur man korrekt löser ett typiskt problem. Det betyder att du sparar tid genom att känna till mönster. På det sättet liknar de algoritmer. Du kan till exempel skapa din egen sorteringsalgoritm med blackjack och siffroroch ägna mycket tid åt det, eller så kan du implementera en som har förståtts och beskrivits under lång tid. Detsamma gäller med designmönster. Dessutom, med designmönster, blir kod mer standard, och när du använder rätt mönster är det mindre troligt att du gör misstag, eftersom mönstrets vanliga fallgropar identifierades och eliminerades för länge sedan. Utöver allt annat hjälper kunskap om mönster programmerare att förstå varandra bättre. Du kan helt enkelt säga namnet på ett mönster istället för att försöka ge en lång förklaring till dina andra programmerare. Sammanfattningsvis hjälper designmönster dig:
  • inte uppfinna hjulet på nytt, utan använd istället standardlösningar;
  • standardisera kod;
  • standardisera terminologi;
För att avsluta detta avsnitt, noterar vi att hela kroppen av designmönster kan delas in i tre stora grupper: Mönster och singel - för alla som möter dem för första gången - 2

Slutligen singelmönstret

Singleton är ett skapande mönster . Detta mönster säkerställer att det bara finns en instans av en klass och tillhandahåller en global åtkomstpunkt för detta objekt. Från beskrivningen bör det framgå att detta mönster bör tillämpas i två fall:
  1. när ditt program kräver att inte mer än ett objekt av en viss klass ska skapas. Till exempel kan ett datorspel ha en Hero-klass och bara ett Hero-objekt som beskriver den enda hjälten i spelet.

  2. när du behöver tillhandahålla en punkt för global åtkomst till ett objekt. Med andra ord måste du göra objektet tillgängligt var som helst i programmet. Tyvärr räcker det inte att bara skapa en global variabel, eftersom den inte är skrivskyddad: vem som helst kan ändra variabelns värde, så att objektets globala åtkomstpunkt kan gå förlorad. Dessa egenskaper hos en Singleton är nödvändiga, till exempel när du har ett objekt som fungerar med en databas, och du behöver komma åt databasen från olika delar av programmet. En Singleton kommer att se till att ingen skriver kod som ersätter den tidigare skapade instansen.
Så en Singleton tillfredsställde dessa två behov: det måste bara finnas ett av en viss typ av objekt i programmet och det måste finnas global tillgång till det. I exemplet på nivå 15 ber kaptenen dig att implementera detta mönster för följande uppgift:
  1. Hitta ett exempel på Singleton med lat initialisering.

  2. Skapa tre singleton-klasser - Sol, Måne, Jord - i separata filer med samma princip.

  3. GenomföraPlanetgränssnitt i klasserna Sol , Måne och Jord .

  4. I statiskt block av Solution -klassen anropareadKeyFromConsoleAndInitPlanetmetod.

  5. ImplementerareadKeyFromConsoleAndInitPlanetmetod funktionalitet:

    • 5.1. Läs en strängparameter från konsolen

    • 5.2. Om parametern är lika med en avPlanetgränssnittets konstanter, skapa lämpliga Planet- objektet.

Efter att noggrant ha läst uppgiftsvillkoren kan vi tydligt se varför en Singleton behövs här. Vi ombeds faktiskt att skapa en instans av var och en av följande klasser: Solen , Månen , Jorden . Det är vettigt att anta att vi inte bör skapa mer än en sol/måne/jord. Annars hamnar vi i en absurd situation, såvida du inte självklart skriver din version av Star Wars. Implementering av Singleton- mönstret i Java i tre steg I Java kan Singleton-beteende inte implementeras med en vanlig konstruktor, eftersom en konstruktor alltid returnerar ett nytt objekt. Därför alla implementeringar av Singletonkoka ner till att dölja konstruktorn, skapa en offentlig statisk metod som styr singelobjektets livstid och "förstöra" alla nya objekt. Om en Singleton nås bör den antingen skapa ett nytt objekt (om ett sådant inte redan finns i programmet), eller returnera ett befintligt. För att åstadkomma detta:
  1. Du måste ge klassen ett privat statiskt fält som lagrar ett enda objekt:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance; // #1
    }
    
  2. Gör (standard)konstruktorn privat. Detta innebär att den inte kan nås utanför klassen och kommer inte att kunna returnera nya objekt:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance;
    private LazyInitializedSingleton(){} // #2
    } 
    
  3. Deklarera en statisk skapelsemetod som kommer att användas för att få singeln:

    
    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
        }
    }
    
Ovanstående exempel är något klumpigt, eftersom vi helt enkelt döljer konstruktorn och tillhandahåller vår egen metod istället för en standardkonstruktor. Eftersom den här artikeln syftar till att säkerställa att CodeGym-studenter kommer i kontakt med detta mönster (och designmönster i allmänhet), kommer nyanserna av mer komplexa singleton-implementeringar inte att beskrivas här. Vi noterar bara att, beroende på programmets komplexitet, kan detta mönster behöva förfinas ytterligare. Till exempel, i en miljö med flera trådar (se artiklar om trådar), kan flera olika trådar komma åt singletonmetoden samtidigt, och koden som beskrivs ovan kommer att sluta fungera, eftersom varje separat tråd kan skapa en instans av klassen. Som ett resultat finns det fortfarande flera olika tillvägagångssätt för att skapa ordentliga gängsäkra singlar. Men det är en annan historia =)

Och till sist... Vad är denna lata initialisering som kaptenen frågade om?

Lat initiering kallas också uppskjuten initiering. Detta är ett programmeringsknep där en resurskrävande operation (och att skapa ett objekt är en resurskrävande operation) utförs på begäran snarare än i förväg. Så vad händer egentligen i vår Singleton Java-kod? Med andra ord, vårt objekt skapas när det nås, inte i förväg. Du bör inte anta att lat initialisering på något sätt är strikt knuten till Singleton -mönstret. Lazy initialisering används också i andra kreativa designmönster, såsom Proxy och Factory Method, men det här är också en annan historia =)
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION