Opprette en ekte singleton klasse i Delphi

Artikkelen beskriver hvordan du oppretter en klasse som følger av Singleton mønster. Klassen er beskrevet vil ta vare på Singleton krav og effekter selv, effektivt forlater programmerer å bruke klassen som noen others.A singleton er en klasse som støtter opprettelsen av bare ett objekt. Det er som datamaskinen din - det er bare ett tastatur. Så hvis du skulle skrive Delphi kode som simulert datamaskinen, vil du bare ønsker ett objekt eksempel å håndtere tastaturet lese, skrive og kontroll activities.Articles om singleton klasser er sjeldne, men det er noen på Internett. Jeg har sett noen i blader også. Men ingen av disse artiklene inkluderer eksempelkoden for å lage en ekte singleton class.By "ekte" mener jeg at klassen selv håndhever ett eksempel kravet, i stedet for å forlate den oppgaven til programmereren. Alle artiklene jeg har sett så langt har krevd programmereren å bruke klassen på en spesiell måte for å håndheve av Singleton pattern.In denne artikkelen vil du se hvordan du kan lage en skikkelig singleton klasse som inneholder logikk for å håndheve ett eksempel regelen . Merk:
konvensjonell tilnærming, der ett eksempel regelen opprettholdes eksplisitt av programmerer, er ikke uten fortjeneste. Ekte singleton klasser som den jeg presenterer her effektivt skjule detaljer og bevissthet om Singleton mønster fra programmereren. Programmereren er lettet over oppgaven med å håndheve mønsteret - det er bra - men programmerer kan også være uvitende om den spesielle naturen i klassen, noe som er dårlig. Hvis du ikke vet at klassen er en singleton klasse da alle slags feil kan dukke opp. Du har blitt advart Skrive codeOur mål er å skrive en klasse som kan brukes slik:
prosedyren Test; Var S1, S2: TSingleton, begynner s1: = TSingleton.Create; s2: = TSingleton.Create; //Gjør noe med s1 og s2 her s2.Free; s1.Free; end; plakater (jeg har utelatt prøve ... endelig blokker og andre sikringstiltak for enkelhets skyld.) Målet er å gjøre TSingleton klassen oppfører seg på en slik måte at både S1 og S2 viser til det samme objektet. Her er hva vi har å gjøre:

instantiate objektet første gang Opprett kalles (når s1 opprettes ovenfor)

Sørg for at når en annen Opprett utføres (s2 ovenfor), det eksisterende objektet er gjenbrukt i stedet for en annen opprettet

Unngå å ødelegge objektet når det er ikke den siste henvisningen som er ødelagt (når s2 er frigjort)

Ødelegg eksempel når den siste henvisningen er ødelagt (når s1 er frigjort ovenfor)
er det en måte å overstyre skapelse og ødeleggelse av et nytt objekt i Delphi? Det er sikkert. I TObject klasse (mor til alle objekter {pun intended}), er det to metoder vi kan bruke:
klasse funksjon NewInstance: TObject; virtuell; prosedyre FreeInstance; virtuell;
NewInstance er ansvarlig for allokering av minne til å holde en ny forekomst av klassen, og FreeInstance er ansvarlig for å frigjøre at minnet når klassen er ferdig med it.These metoder kontrollere hva som skjer når objektet er opprettet og når objektet blir ødelagt. Hvis vi overskrive denne koden, kan vi endre standard virkemåte for å arbeide si en singleton klasse krever. Ingenting å it.Tracking tilfeller er litt mer komplisert. Vi må:


    Hold orden på hver eksisterende forekomst av klassen vår

    Hold styr på hvor mange referanser det er til dette tilfellet bare

    Opprett et nytt objekt når noe tilfelle finnes

    Destroy objektet når den siste referansen fjernes
    for å holde styr på en eksisterende forekomst, vil vi bruke en global variabel. Egentlig vil den variable slutt bli erklært inne i Implementering del av en enhet slik at det ikke vil være en sann global variabel. Men omfanget må være tilstrekkelig til å spore alle Lag og gratis samtaler. Vi kaller variabelen Instance så vi vet hva det refererer to.As for å holde styr på hvor mange referanser eksisterer, trenger vi en annen variabel. Vi kan den inne i klassen eller gjøre det til en sortering av global lignende instans. Jeg velger det siste måten, men gjør det du føler er best. Jeg vil kalle denne variabelen Ref_Count.We nå har to variabler:
    Var Instance: TSingleton = null; Ref_Count: Integer = 0;
    jeg initialisere variabler slik som i utgangspunktet har de ikke inneholder noe søppel. Jeg vet at kompilatoren gjør dette automatisk, så dette er bare en lesbarhet issue.We'll trenger å erklære TSingleton klasse over variable blokk, og hvis du tar en titt på eksempel filer som du kan laste ned på slutten av denne artikkelen vil du se at jeg har satt erklæringen i grensesnittet delen av enheten, slik at det er synlig utenfor det. Her er erklæringen av TSingleton klasse:
    skriver TSingleton = klasse public class funksjon NewInstance: TObject; styre; prosedyre FreeInstance; styre; klasse funksjon RefCount: Integer; enden,
    jeg lagt RefCount funksjonen slik at vi kan se at det faktisk fungerer, og det er ofte nyttig å kunne lese hvor mange referanser til objektet eksisterer. Det er ikke nødvendig, men slik at du ikke trenger å legge den til dine singleton klassene hvis du ikke trenger it.Ok, nå for gjennomføringen av de tre metodene:
    prosedyre TSingleton.FreeInstance, begynner desember (Ref_Count ); if (Ref_Count = 0), og start Instance: = null; //Destroy private variabler her arvet FreeInstance; end, end, klasse funksjon TSingleton.NewInstance: TObject; begynne if (ikke Assigned (Instance)), og start Instance: = arvet NewInstance; //Initial private variabler her, som dette: //TSingleton (resultater) .Variable: = verdi; slutt; Resultat: = Instance Inc (Ref_Count); end; klasse funksjon TSingleton.RefCount: Integer; begynne Resultat: = Ref_Count; end;
    Og det er det når du ringer TSingleton konstruktør, er en samtale plassert til NewInstance metoden erklært! TObject. Denne metoden tildeler minne til å holde det nye objektet og returnerer det til konstruktøren. Konstruktøren bruker som minne og til slutt returnerer en peker til minnet til koden som kalte konstruktøren. Denne pekeren er vanligvis lagret i en variabel mens objektet er i bruk.Jeg har overstyrt NewInstance metoden slik at det vil fordele minnet bare hvis ingen forekomst av klassen eksisterer. Hvis det er en eksisterende forekomst, returnerer funksjonen bare forekomsten til konstruktøren slik at det vil være reused.If vi kaller konstruktøren tre ganger, et objekt opprettes bare første gang. De to andre samtaler bare bruke det første objektet. Referanse teller variable fortelle oss at vi har tre referanser til enkelt instance.When programmet kaller destructor, er et kall til FreeInstance plassert for å frigjøre minne som er tildelt i konstruktøren. Denne metoden også overstyres slik at objektet er ødelagt bare når den siste referansen er removed.If du har tenkt å bruke et enkelt inne en flertrådet program, behandle objektet som du ville enhver variabel du dele mellom trådene. Fordi det er akkurat det du gjør: dele den mellom gjengene. Så du må ta ekstra hensyn når du bytter data.Simplicity itselfAs du kan se, og skaper en singleton klasse krever ikke mye innsats, akkurat den rette kunnskapen og noen få linjer med kode. Koden min fungerer fint i Delphi 5. Teknikken vil sannsynligvis fungere fint med eldre versjoner av Delphi, men jeg har ikke testet den så jeg ikke gjør noen guarantees.Before jeg gi deg filen til å spille med, la meg gi deg noen få ord av advarsel.

    ikke ned fra en singleton klasse. Grunnen for det er at det er bare ett eksempel og referansetellevariabel. Hvis du utlede to klasser fra TSingleton, vil bare ett objekt opprettes. Den andre klassen vil gjenbruke det objekt, som vil være et eksempel på en annen klasse. Ikke gå ned den veien!
  1. Du kan ikke lage Singleton komponenter av den enkle grunn av eierskap. En komponent er eid av en form og en komponent kan ikke være eid av flere andre komponenter.
  2. Husk at konstruktøren og destructor bli kalt for hver nye referanse som de er skapt og ødelagt. Ikke initial private variabler i konstruktøren, og ikke frigjøre dem i destructor. I stedet bygger på at koden inn i NewInstance og FreeInstance metoder, slik som vist i kommentarene.
  3. Rekkefølgen for å justere Ref_Count i de to fremgangsmåter i forbindelse med resten av koden i disse to metodene er kritisk. Det har å gjøre med riktig skapelse og ødeleggelse når noe går galt. Hvis initialisering kode hever et unntak, vil ordren om å gjøre ting som vist ovenfor sørge for at klassen er ødelagt riktig. Endre denne koden ved fare Filen som du kan laste ned er bare en kopi av den enheten som erklærer singleton klasse er beskrevet i denne article.Link til fil: CodeCentral oppføring 15083.I'm at du kan finne noen steder hvor en singleton klasse kommer i hendig, og nå har du verktøy for å lage din egen! Hvis du ønsker å komme i kontakt med meg, er min e [email protected] programmering!