2012-11-02 16 views
35

Während ich kürzlich mit Objective-C und verschiedenen darin geschriebenen Bibliotheken gearbeitet habe, habe ich zwei wirklich populäre Singleton-Muster bemerkt. Eine Version ruft die Singleton-Instanz ab und ruft ihre Instanzmethoden auf. Eine andere Version macht nur Klassenmethoden verfügbar und gibt Ihnen nie eine Instanz, mit der Sie arbeiten können. Alle haben den Zweck, den Zugriff auf eine einzelne Ressource (StoreKit, CoreData, Parse API usw.) zu abstrahieren. Zum Beispiel ist hier der erste Ansatz in MKStoreKit verwendet:Singleton-Instanz vs Klassenmethoden

// initialize singleton during app boot 
[MKStoreManager sharedManager] 

// sometime later in the app 
[[MKStoreManager sharedManager] buyFeature:kFeatureAId 
           onComplete:^(NSString* purchasedFeature) 
{ 
    NSLog(@"Purchased: %@", purchasedFeature); 
} 
           onCancelled:^ 
{ 
    NSLog(@"User Cancelled Transaction"); 
}]; 

oder alternativ NSUserDefaults, UIApplication etc .. Der andere Ansatz in MagicalRecord gesehen werden kann oder hier mit Parse API:

// configure API credentials sometime during app boot 
[Parse setApplicationId:@"123456" 
       clientKey:@"123456"]; 

// sometime later 
PFObject *testObject = [PFObject objectWithClassName:@"TestObject"]; 
[testObject setObject:@"bar" forKey:@"foo"]; 
[testObject save]; 

Was sind einige Vor- und Nachteile der beiden Ansätze und ist einer von ihnen grundsätzlich besser als der andere?

Wenn Sie die gemeinsam genutzte Instanz nicht abrufen müssen, sparen Sie einige Bildschirmfehler (der Leistungsunterschied ist wahrscheinlich irrelevant), aber schraube ich mich auf andere Weise ein, zum Beispiel testbar?

Danke!

Antwort

27

Es gibt zwei verschiedene Möglichkeiten, um den Ansatz zu implementieren, basierend auf Klassenmethoden:

  • Machen Sie eine einzelne Instanz eine Klasse von jedem versteckt verwenden und verstecken ihre Methoden hinter Wrapper-Klasse Methoden mit identischen Signaturen oder
  • Make-Klasse Methoden, die

die Auswirkungen der ersten Implementierung die ganze Arbeit machen, dass alles, was man mit einem Singleton tun können, um Sie mit dem verborgenen Singleton tun können:

  • eine Unterklasse mit wird eine Möglichkeit
  • die Instanz in der Mitte der Laufschalt ist einfach
  • die staatlichen Leben in Instanzvariablen
  • Initialisierung das bekannte Muster

Wenn Sie folgt Für eine Implementierung, die kein Singleton verwendet, würden Sie sich auf statische Variablen verlassen, um Ihren aktuellen Status beizubehalten. Das ist eine legitime Wahl, aber das Initialisierungsmuster wird anders (vielleicht sogar unter Verwendung eines dispatch_once), Sie können die Implementierung nicht in der Mitte wechseln, ohne sich auf einige hässliche if Bedingungen zu verlassen, und die Verwendung einer Unterklasse wird viel komplizierter.

Das Testen der ersten Implementierung ist etwas einfacher als das Testen der zweiten, da Sie eine separate Implementierung des Singleton für Tests bereitstellen können, vielleicht durch die Hintertür; Bei einer statischen Implementierung kann diese Route nicht verwendet werden.

Zusammenfassend würde ich eine Singleton-basierte Lösung verwenden, wobei das Singleton optional hinter einer "Fassade" verborgen ist, die Zugriff auf Singleton-Methoden bietet. Ich würde keine Implementierung verwenden, bei der alle Zustände in statischen Variablen platziert werden müssen.

+1

Große Antwort, danke! –

+0

Schöne Antwort, aber ein kleines Beispiel macht es viel einfacher zu verstehen. – atulkhatri

7

Ein Vorteil des Singleton-Ansatzes ist, dass es trivial wird, andere Instanzen zuzulassen, wenn Sie dies benötigen. Wenn Sie den Klassenmethodenansatz wählen, erhalten Sie ohne viel Refactoring alles.