values unity scenes prefs playerprefs pass one from escenas entre data another objective-c oop design-patterns

objective-c - scenes - unity save prefs



Singleton Instance vs Class Methods (2)

Mientras trabajaba recientemente con Objective-C y varias bibliotecas escritas en él, noté dos patrones de singleton realmente populares. Una versión obtiene la instancia singleton y llama a sus métodos de instancia y otra versión solo expone métodos de clase y nunca le da una instancia para trabajar. Todos tienen el propósito de abstraer el acceso a un único recurso (StoreKit, CoreData, Parse API, etc.). Por ejemplo, aquí está el enfoque anterior utilizado en MKStoreKit:

// 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"); }];

o alternativamente NSUserDefaults, UIApplication, etc. El otro enfoque se puede ver en MagicalRecord o aquí con 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];

¿Cuáles son algunos de los pros y los contras de los dos enfoques y uno de ellos es fundamentalmente mejor que el otro?

No tener que recuperar la instancia compartida ahorra un poco de espacio en la pantalla (la diferencia de rendimiento es probablemente irrelevante), pero ¿me estoy volviendo loco de alguna otra manera, por ejemplo, la capacidad de prueba?

¡Gracias!


Hay dos formas diferentes de implementar el enfoque basado en los métodos de clase:

  • Cree una instancia singleton utilizando una clase oculta para todos, y oculte sus métodos detrás de los métodos de la clase contenedora con firmas idénticas, o
  • Haz métodos de clase que hagan todo el trabajo

Las implicaciones de la primera implementación son que todo lo que puedes hacer con un singleton, puedes hacerlo con el singleton oculto:

  • usar una subclase se convierte en una posibilidad
  • cambiar la instancia en el medio de la ejecución es fácil
  • el estado vive en variables de instancia
  • la inicialización sigue el patrón familiar

Si opta por una implementación que no utiliza un singleton, debería confiar en variables estáticas para mantener su estado actual. Esa es una opción legítima, pero el patrón de inicialización se vuelve diferente (quizás incluso utilizando un dispatch_once ), no puede cambiar la implementación en el medio sin depender de algunas condiciones feas, y el uso de una subclase se vuelve mucho más complicado.

Probar la primera implementación es algo más fácil que probar el segundo, porque puede proporcionar una implementación separada del singleton para la prueba, quizás a través de la puerta de atrás; con una implementación estática, esta ruta no puede tomarse.

Para resumir, usaría una solución basada en singleton, con el singleton opcionalmente escondido detrás de una "fachada" que proporciona acceso a los métodos de Singleton. No usaría una implementación donde todo el estado debe colocarse en variables estáticas.


Una ventaja del enfoque singleton es que resulta trivial permitir otras instancias si es necesario. Si tomas el enfoque del método de clase, eso es todo lo que obtienes sin mucha refactorización.