Back home

Patrones de diseño por tutoriales: el poder de la programación orientada a objetos (parte 2)

Viaje de patrones de diseño: el poder de la programación orientada a objetos 2

Patrones de diseño por tutoriales: el poder de la programación orientada a objetos (parte 2)

Patrón Singleton: patrón de diseño singleton puro y semi-singleton en Swift Patrón Singleton: Patrones de diseño Singleton puro y Semi-Singleton en Swift

Requisitos previos: esta serie de blogs requiere un nivel intermedio de experiencia en programación orientada a objetos. Debe tener conocimientos básicos sobre clase, objeto, constructor, herencia, valor y tipo de referencia. Un nivel intermedio adquirirá conocimientos y los expertos los perfeccionarán leyendo esta serie de principio a fin. Requisitos previos: esta serie de blogs requiere experiencia intermedia en programación orientada a objetos. Debe tener conocimientos básicos de clases, objetos, constructores, herencia, valores y tipos de referencia. Los usuarios intermedios obtendrán conocimientos, mientras que los expertos mejorarán sus conocimientos leyendo esta serie de principio a fin.

Clase única

clase singleton

En programación orientada a objetos, una clase singleton es una clase que puede tener un solo objeto durante todo el ciclo de vida de una aplicación o proyecto. En programación orientada a objetos, una clase singleton es una clase que puede tener un solo objeto durante todo el ciclo de vida de una aplicación o proyecto.

El patrón de diseño Singleton es parte del código del ciclo de vida de las aplicaciones iOS. Por ejemplo, en un proyecto de iOS, la clase UIApplication es el mejor ejemplo de una clase singleton, que el sistema iOS crea al iniciar la aplicación y se pasa al AppDelegate como parámetro en el método application:didFinishLaunchingWithOptions:. El patrón de diseño singleton es parte del código del ciclo de vida de la aplicación iOS. Por ejemplo, en un proyecto de iOS, la clase UIApplication es el mejor ejemplo de una clase singleton, que el sistema iOS crea cuando se inicia la aplicación y se pasa a AppDelegate como parámetro en el método application:didFinishLaunchingWithOptions:.

Hay dos tipos de patrones de diseño Singleton.

Hay dos tipos de patrones de diseño singleton.

  1. Patrón de diseño singleton puro Patrón de diseño singleton puro

  2. Patrón de diseño semi-singleton Patrón de diseño semi-singleton

Patrón de diseño puro-Singleton:

Patrón de diseño puro-Singleton:

En este patrón, un programador que utiliza la funcionalidad de una clase puramente única no puede crear una instancia de la clase. Un programador solo puede llamar a métodos y acceder a propiedades disponibles para la clase singleton utilizando la instancia predefinida de esa clase. En este patrón, los programadores que utilizan la funcionalidad de una clase singleton pura no pueden crear instancias de esa clase. Los programadores pueden llamar a métodos y acceder a las propiedades disponibles solo mediante el uso de una instancia predefinida de una clase singleton.

El objeto de una clase puramente única se crea automáticamente durante el inicio de la aplicación con parámetros predefinidos mencionados por el desarrollador que creó esa clase. Durante el inicio de la aplicación, los objetos de clases singleton puras se crean automáticamente utilizando parámetros predefinidos mencionados por el desarrollador que creó la clase.

Las clases puramente únicas deben marcarse como finales para evitar confusiones en la herencia. En Swift, también puedes utilizar la estructura para lograr el mismo concepto. Las clases singleton puras deben marcarse como finales para evitar confusión en la herencia. En Swift, también puedes usar estructuras para implementar el mismo concepto.

Un programador no puede heredar la clase singleton pura. Cuando intentas heredar cualquier clase en Swift, debes llamar al constructor de la superclase. No es posible llamar al constructor de la superclase en una clase singleton pura porque todos los constructores de la clase singleton pura siempre están marcados como privados. Los programadores no pueden heredar de clases singleton puras. Cuando intentas heredar de cualquier clase en Swift, debes llamar al constructor de la superclase. No es posible llamar al constructor de la superclase en la clase singleton pura porque todos los constructores de la clase singleton pura están marcados como privados.

Entendamos este patrón de diseño de una manera sencilla con el siguiente ejemplo. Entendamos este patrón de diseño de forma sencilla a través del siguiente ejemplo.


//PureSingletonDesignPatterExample1.swift :

// Hitendra Solanki
// Pure-singleton design pattern Playground example
final class LogManager {
  //shared and only one available object
  static let logger: LogManager = LogManager(databaseURLEndpoint: "https://www.hitendrasolanki.com/logger/live")
  
  private var databaseURLEndpoint: String
  
  //marked as private, no one is allowed to access this initialiser outside of the class
  private init(databaseURLEndpoint: String) {
    self.databaseURLEndpoint = databaseURLEndpoint
  }
  
  func log(_ value: String...){
    //complex code to connect to the databaseURLEndpoint and send the value to server directly
  }
}

//This is function in playground which executes our test code
func main(){
  LogManager.logger.log("test log from medium blog") //this will log on "/live" endpoint
}

//call main to execute our test code
main()


En el ejemplo anterior, PureSingletonDesignPatterExample1.swift hemos marcado todos los métodos init como privados de la clase LogManger para que nadie pueda crear una instancia de esa clase. Si intentamos crear una subclase de LogManger, el compilador le dará un error. En el ejemplo anterior, PureSingletonDesignPatterExample1.swift, hemos marcado todos los métodos init como métodos privados de la clase LogManger, por lo que nadie puede crear una instancia de esta clase. Si intentamos crear una subclase de LogManger, el compilador le dará un error.

UIApplication y AppDelegate son ejemplos de la clase singleton pura. ¿Alguna vez ha intentado crear manualmente un objeto de la clase UIApplication? Intente hacerlo y ejecute la aplicación. [¿Qué pasó? La aplicación falló, ¿verdad? -He probado este fallo en Swift 5, XCode 10.2] UIApplication y AppDelegate son ejemplos de clases singleton puras. ¿Alguna vez ha intentado crear manualmente un objeto de clase UIApplication? Intente hacerlo y ejecutar la aplicación. La aplicación falla, ¿verdad? - He probado este fallo en Swift 5, XCode 10.2]

Limitaciones del patrón de diseño Singleton puro,

Limitaciones del patrón singleton puro,

No podemos probar la clase singleton pura con los datos de prueba. En el ejemplo anterior PureSingletonDesignPatterExample1.swift, supongamos que desea probar la clase LogManager apuntándola a alguna URL del modo de prueba en lugar de la URL del modo de producción; no podemos hacerlo cuando escribimos casos de prueba en el destino XCTest. No podemos probar clases singleton puras con datos de prueba. En el ejemplo anterior, PureSingletonDesignPatterExample1.swift, suponiendo que desea probar la clase LogManager, apúntelo a alguna URL del modo de prueba en lugar de la URL del modo de producción; no podemos hacer esto cuando escribimos casos de prueba en el destino XCTest.Podemos superar esta limitación convirtiendo nuestra clase singleton pura en clase semi-singleton o utilizando el patrón de inyección de dependencia. Escribiré un artículo dedicado al patrón de inyección de dependencia. Por ahora, continuemos con el patrón de diseño semi-singleton. Podemos superar esta limitación convirtiendo nuestra clase singleton pura en una clase semi-singleton o utilizando el patrón de inyección de dependencia. Escribiré un artículo específicamente sobre patrones de inyección de dependencia. Ahora, sigamos usando el patrón de diseño semi-singleton.

Patrón de diseño semi-singleton:

Patrón de diseño semi-singletón:

  • En el patrón de diseño semi-singleton, un programador que usa la clase puede crear un objeto de la clase singleton si es necesario. además de permitir también llamar a métodos y utilizar propiedades de la clase singleton. En el patrón de diseño semi-singleton, el programador que utiliza la clase puede crear objetos de la clase singleton si es necesario. Así como propiedades que permiten llamar a métodos y utilizar clases singleton.

  • Un programador también puede heredar la clase semi-singleton si el desarrollador de la clase singleton no marca el singleton como final. En el patrón de diseño semi-singleton no es necesario marcar la clase como final. Los programadores también pueden heredar de clases semi-singleton si el desarrollador de la clase singleton no marca la clase singleton como final. En el patrón semi-singleton, no es necesario marcar la clase como final.


//SemiSingletonDesignPatterExample1.swift
// Hitendra Solanki
// Semi-singleton design pattern Playground example
//In semi-singleton design pattern, marking the class as final is optional
final class LogManager {
  //shared object
  static let logger: LogManager = LogManager(databaseURLEndpoint: "https://www.hitendrasolanki.com/logger/live")
  
  private var databaseURLEndpoint: String
  
  //not marked as private, anyone is allowed to access this initialiser outside of the class
  init(databaseURLEndpoint: String) {
    self.databaseURLEndpoint = databaseURLEndpoint
  }
  
  func log(_ value: String...){
    //complex code to connect to the databaseURLEndpoint and send the value to server directly
  }
}

//This is function executes our main code
func main(){
  LogManager.logger.log("main log from medium blog on live server endpoint") //this will log on "/live" endpoint
}


// This is function executes our TEST MODE code
// Here in playground, Hitendra Solanki created this method for the demostratino purpose only
// Usually we write this kind of test codes, inside the test targe of the XCode-project
func testThatLogManger(){
  
  //we are allowed to create an instace of class LogManager,
  //because it follows the Semi-Singleton design patterns
  let logManagerTestObject = LogManager(databaseURLEndpoint: "https://www.hitendrasolanki.com/logger/test")
  
  logManagerTestObject.log("test log from medium blog on test server endpoint") //this will log on "/test" endpoint
}

main() //call main
testThatLogManger() //call test execution

  • En el ejemplo anterior, SemiSingletonDesignPatterExample1.swift, no hemos marcado el método init como privado, por lo que podemos crear varias instancias de la clase semi-singleton para eliminar la dependencia de la propiedad databaseURLEndpoint. Ahora podemos crear un objeto de la clase LogManger usando cualquier valor de databaseURLEndpoint, ahora nuestra clase LogManger sigue el patrón semi-singleton. En el ejemplo anterior, SemiSingletonDesignPatterExample1.swift, no marcamos el método init como privado, por lo que podemos crear varias instancias de la clase semi-singleton para eliminar la dependencia de la propiedad databaseURLEndpoint. Ahora podemos crear objetos de la clase LogManger usando cualquier valor de base de datosURLEndpoint y ahora nuestra clase LogManger sigue un patrón semi-singleton.

UserDefault, FileManager, NotificationCenter son ejemplos de clases semi-singleton. Podemos utilizar objetos compartidos predefinidos de UserDefault, FileManager y NotificationCenter que son UserDefault.standard, FileManager.default y NotificationCenter.default. UserDefault, FileManager y NotificationCenter son ejemplos de clases semisingleton. Podemos utilizar objetos compartidos predefinidos como UserDefault, FileManager y NotificationCenter, que son UserDefault.standard, FileManager.default y NotificationCenter.default.

El objeto predefinido de clases puras o semi-singleton siempre vive en la memoria y nunca se destruye hasta que se cierra la aplicación. Un objeto definido por el programador de clase semi singleton destruido después de que se completa el alcance del objeto. Los objetos predefinidos de clases puras o semi-singleton siempre existen en la memoria y no se destruyen hasta que se cierra la aplicación. Un objeto definido por el programador de una clase semi-singleton se destruye una vez que se completa el alcance del objeto.

Pregunta: ¿Cuál es una mejor manera, “patrón de diseño singleton puro” o “patrón de diseño semi-singleton”, cuando debo usar el primero y cuando el otro? Pregunta: ¿Cuál es mejor, “Patrón de diseño Singleton puro” o “Patrón de diseño Semi-Singleton”? ¿En qué circunstancias se debe utilizar?

Esto depende totalmente de las responsabilidades de tu clase. Si ha creado una clase singleton en su proyecto y necesita cambiar algunas de las propiedades en algún momento o si desea agregar más responsabilidades a la clase agregando nuevos métodos en el futuro y si necesita sus casos de prueba también con datos simulados para los métodos recién agregados, debe optar por el patrón de diseño semi-singleton. Todo depende de la funcionalidad de tu clase. Si ha creado un proyecto de clase singleton y necesita cambiar algunas propiedades en algún momento, o en el futuro desea agregar nuevos métodos y necesita usar datos simulados para probar los métodos recién agregados, debe adoptar el patrón de diseño semi-singleton.

Si creó su clase, ya terminó con las pruebas unitarias y desea publicarla a través de un marco o biblioteca, puede optar por patrones de diseño puros. Debido a que usted creó la clase y algún otro desarrollador la usará, las pruebas unitarias de su clase singleton son su responsabilidad antes del lanzamiento, no la responsabilidad del desarrollador que la está usando. Si creó su clase, la probó por unidad y desea distribuirla a través de un marco o biblioteca, puede usar el patrón de diseño Pure Singleton. Debido a que usted creó esta clase, otros desarrolladores la usarán, por lo que probar la clase singleton antes de lanzarla es su responsabilidad, no la responsabilidad de los desarrolladores que la usan.

Haga clic para ver el texto original