Design Patterns: Singletons

Design Mønstre: Singletons
26
Del
6
Del

Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert å bare $ 3. Ikke gå glipp av.

Design mønstre blir ofte betraktet som en mer avansert emne og derfor ignorert eller oversett av nye folk til iOS eller OS X utvikling. Det finnes imidlertid en rekke designmønstre alle aspirerende iOS eller OS X utvikler vil bli møtt med fra dag én. Av Singleton mønsteret er et slikt mønster.

Før vi begynner å se på teknikker for å implementere Singleton mønster i Swift og Objective-C, vil jeg gjerne ta et øyeblikk å forstå Singleton mønster, inkludert sine fordeler og ulemper.

1. Hva er en Singleton

Sanne & Funksjonelle Singletons

The Singleton mønsteret er uløselig knyttet til objektorientert programmering. Definisjonen av Singleton mønsteret er enkelt, bare én forekomst av singleton klasse kan opprettes eller er i live til enhver tid.

Brent Simmons, men nyansene denne definisjonen ved å gjøre et skille mellom sant
enkeltfødte og funksjonelle
enkeltfødte. Brent definerer sanne enkeltfødte som klasser som alltid returnere samme forekomst av seg selv. Det er ikke mulig å lage mer enn én forekomst av klassen. Funksjonelle enkeltfødte opprettes én gang og brukes flere steder.

Jeg er sikker på at mange utviklere ikke vil kategorisere funksjonelle enkeltfødte som enkeltfødte, men jeg liker skillet Brent gjør. Funksjonelle enkeltfødte mangler ofte ulempene typiske å true enkeltfødte. Vi skal se på disse ulempene senere i denne artikkelen.

Hvis du er kjent med iOS eller OS X utvikling, så vil du legge merke til at Apples rammeverk gjøre bruk av Singleton mønster. En iOS-applikasjon, for eksempel, kan bare ha én forekomst av UIApplication klassen, som du kan få tilgang til gjennom sharedApplication klassen metoden
UIApplication * sharedApplication = [UIApplication sharedApplication];. La sharedApplication = UIApplication.sharedApplication ()

Selv om UIApplication klassen gir deg tilgang til UIApplication enkelt, ingenting som hindrer deg fra å eksplisitt Instantiating en UIApplication eksempel
UIApplication * newApplication = [[UIApplication Alloc] init];. la newApplication = UIApplication ()

Resultatet, derimot, er en runtime unntak. Unntaket sier klart at bare én forekomst av UIApplication klassen kan være i live til enhver tid. Med andre ord ble UIApplication klassen utformet med Singleton mønster i tankene
*** Avslutte app grunn uoppfanget unntak 'NSInternalInconsistencyException', grunn: ".. Det kan bare være én UIApplication eksempel '
Fordeler

Tilgjengelighet

Den mest åpenbare fordelen av Singleton mønsteret er tilgjengelighet. Vurdere UIApplication klassen som et eksempel. Ved å importere den UIKit rammeverket, er UIApplication singleton tilgjengelig fra hvor som helst i prosjektet. Ta en titt på følgende eksempel på en UIViewController underklasse
#import < UIKit /UIKit.h >interface ViewController. UIViewController @ slutten # import "ViewController.h"@implementation ViewController # pragma mark - # pragma mark Vis Livet Cycle- (void) viewDidLoad {[super viewDidLoad]; //Tilgang Application Singleton UIApplication * søknad = [UIApplication sharedApplication];} @ slutten

Kontroll og Behavior

Det er noen ganger nyttig eller avgjørende at bare én forekomst av en klasse er i live til enhver tid. Den UIApplication klassen er et eksempel på dette kravet. Andre eksempler kan inkludere klasser for logging, caching, eller I /O-operasjoner.

Når det er sagt, er det viktig å forstå at enkeltfødte er et middel for å oppnå kontroll og atferd. Defensive koding teknikker kan gi deg samme resultat uten den mentale overhead av Singleton mønsteret.

Ulemper

Global State

Ved å opprette en enkelt, du er i hovedsak å skape global tilstand. Det er viktig at du er klar over dette. For noen år siden skrev Miško Hevery en stor artikkel om Singleton mønster der han forklarer hvorfor mønsteret bør unngås. Miško understreker at global stat er hovedårsaken til at enkeltfødte er skadelig.

Det finnes unntak skjønt. For eksempel kan enkeltfødte som er uforanderlig gjøre lite skade. Du er fortsatt skaper global tilstand, men at tilstanden er uforanderlig. Miško nevner også loggere som a-noe-akseptabel bruk av Singleton mønsteret siden staten flyter i én retning, fra programmet inn i logger.

Tight Coupling

De fleste objektorienterte programmeringsspråk vurdere tett kobling av moduler en dårlig praksis. Sagt på en annen, er det anbefalt å kople moduler så mye som mulig. Dette setter Singleton mønster i et dårlig sted og enkeltfødte blir derfor betraktet som en dårlig praksis av mange respekt programmerere. Noen utviklere gå så langt som vurderer det en anti-mønster som bør unngås.

For å bedre forstå problemet, bør du vurdere følgende scenario. Du har opprettet en iOS-applikasjon med en nettverkskomponenten der du får tilgang til UIApplication enkelt. IOS-applikasjonen er en slik suksess at du vurdere å opprette en OS X-program. Den UIApplication klasse, men er ikke tilgjengelig på OS X på grunn av mangel på UIKit rammeverket. Dette betyr at du må refactor eller endre nettverkskomponenten av iOS-programmet.

Det finnes en rekke løsninger for å løse dette problemet, men poenget jeg ønsker å gjøre er at du tett har kombinert nettverk modulen til UIKit rammer, UIApplication klasse i særdeleshet.

Gjenbruk

Tett integrasjon er ofte nært knyttet til gjenbruk. En tett koblet objekt grafen er svært ofte vanskelig å gjenbruke uten refactoring. Dårlig gjenbruk er noen ganger uunngåelig, men det er absolutt noe å huske på når du utvikler programvare.

2. Opprette en Singleton

Objective-C

Opprette et enkelt inne Objective-C er veldig enkelt å gjøre. I det følgende kodebiten, skaper vi og implementere en logging klasse, Logger. Vi får tilgang til singleton objekt gjennom sharedLogger klassen metoden
#import < Foundation /Foundation.h >interface Logger. NSObject # Pragma mark - # pragma mark Klassemetoder + (Logger *) sharedLogger;end

implementeringen er enkel. Vi erklærer en statisk variabel _sharedInstance som vil holde en referanse til singleton objekt. Vi påberope dispatch_once, en Grand Central Dispatch funksjon, og passerer i en blokk der initial vi en forekomst av Logger klassen. Vi lagrer en referanse til forekomsten i _sharedInstance
#import "Logger.h"@implementation Logger # Pragma mark - # pragma mark Klassemetoder + (Logger *) sharedLogger {statisk Logger * _sharedInstance = null.; statisk dispatch_once_t oncePredicate; dispatch_once (& oncePredicate, ^ {_sharedInstance = [[selvtillit Alloc] init];}); returnere _sharedInstance;} @ slutten

dispatch_once funksjonen sørger for at blokken vi passerer det utføres en gang for levetiden til programmet. Dette er veldig viktig siden vi bare ønsker å initial én forekomst av Logger klassen.

oncePredicate variable som er gått som det første argumentet til dispatch_once funksjonen brukes av dispatch_once funksjon for å sikre at blokken blir utført bare én gang.

sharedLogger klassen metoden returnerer Logger eksempel ved å returnere referansen lagret i _sharedInstance. Gjennomføringen av sharedLogger kan se skremmende i starten, men jeg er sikker på at du enig i at ideen er veldig enkel.

Swift

For å gjennomføre Singleton mønster i Swift, gjør vi bruk av klasse konstanter, som ble introdusert i Swift 1.2. Hvis du har problemer med under kodebiten, så sørg for at du bruker Xcode 6.3+.
Klasse Logger {statiske la sharedInstance = Logger ()}

La meg gå gjennom den korte gjennomføringen av Logger klasse. Vi starter med å erklære en klasse som heter Logger. Å gjennomføre Singleton mønster, erklærer vi en type eiendom, sharedInstance, av type Logger.

Ved å bruke den statiske nøkkelordet, den sharedInstance konstant er knyttet til Logger klassen i stedet for forekomster av klassen. Den sharedInstance konstant betegnes som en skriver eiendom
ettersom det er knyttet til den type, det vil si den Logger klasse. Vi får tilgang til singleton objekt gjennom Logger klassen.
Logger.sharedInstance

Du lurer kanskje på hvorfor vi ikke bruker dispatch_once funksjon som vi gjorde i Objective-C gjennomføring. Under panseret, bruker Swift allerede dispatch_once når initialisering statiske konstanter. Det er noe du får gratis i Swift.

En annen vanlig metode for gjennomføring av Singleton mønsteret er ved å utnytte nestede typer. I følgende eksempel, erklærer vi en beregnet typen eiendom, sharedInstance, av type Logger. I nedleggelsen av den beregnede typen eiendom, erklærer vi en struktur som heter Singleton. Strukturen definerer en konstant typen eiendom, f.eks av typen Logger
klasse Logger {class Var sharedInstance: Logger {struct Singleton {statiske la eksempel: Logger = Logger ()} returnere Singleton.instance}}.

Tilgang til Singleton formål er den samme for begge strategier. Hvis du bruker Swift 1.2, så jeg anbefaler å bruke den første tilnærmingen for sin kortfattethet og enkelhet.

3. Når man skal bruke Singletons?
Jeg antar at det er fristende, hvis det eneste verktøyet du har er en hammer, for å behandle alt som om det var en spiker. - Abraham Maslow

Da jeg først hørte om Singleton mønster, var jeg spent på hvor nyttig det ville være i mitt neste prosjekt. Det er meget fristende å bruke et verktøy som virker til å løse mange problemer. Ved første øyekast kan det Singleton mønsteret ser ut som en sølvkule eller en gyllen hammer, men det er ikke det av Singleton mønsteret er.

For eksempel, hvis du bruker en singleton bare for å gjøre det lett tilgjengelig , så du kan være ved hjelp av Singleton mønster for de gale grunnene. Det er ikke fordi Apple bruker av Singleton mønster i sine egne rammer at det er den riktige løsningen på alle problemer.

Singletons kan være svært nyttig, men de blir ansett som et anti-mønster av mange erfarne programmerere. De fleste av dem har hatt dårlige erfaringer med mønster for å komme til denne konklusjonen. Lære av sine feil og bruke dem med måte.

Jeg anser ikke av Singleton mønsteret en anti-mønster, men det er et mønster som bør brukes med forsiktighet. Hvis du føler deg fristet til å slå et objekt i et enkelt, spør deg selv spørsmålet om det er noen annen måte som du kan løse problemet. I de fleste tilfeller er av Singleton mønsteret ikke er den eneste løsningen som er tilgjengelig. En alternativ løsning kan kreve mer arbeid eller en bit av overhead, men det er trolig bedre i det lange løp.

De funksjonelle enkeltfødte Brent Simmons viser til er ofte en helt gyldig alternativ til ekte enkeltfødte. Det er ingenting galt med å opprette en forekomst av en klasse, og den sendes til objektene som trenger det. Vurdere denne tilnærmingen neste gang du er om å skape et annet enkelt.

Konklusjon

The Singleton mønsteret er enkel og kraftig, men det bør brukes med måte. Noen av dine kolleger kan råde deg mot det, men jeg tror det er viktig å vurdere bruken og døm selv om du tror det er et nyttig tillegg til verktøykassen.