Xojo es un entorno de desarrollo multiplataforma nativo en el que se utiliza un lenguaje de programación orientado a objetos (OOP). Esto significa que cada vez que afrontemos un nuevo proyecto (aplicación) podremos reutilizar gran parte del trabajo realizado previamente, tales como clases, interfaces o módulos, sin la necesidad de que debamos de escribir nuestro código una y otra vez de forma repetitiva.
En defintiva, se trata de aumentar nuestra productividad al tiempo que reducimos la posible aparición de fallos o bugs en nuestros productos; dado que estaremos reutilizando los mismos componentes largamente usados y, por tanto, también probados.
Puedes descargar el proyecto utilizado en este ejemplo desde este enlace.
Cuando utilizamos lenguajes de programación orientados a objetos nos topamos tarde o temprano con los Patrones de Diseño. Podemos definirlos como el conjunto de soluciones que se han identificado con el paso del tiempo frente a una serie de situaciones comunes en el diseño de nuestras aplicaciones orientadas a objetos. Es decir, recetas sobre cómo podemos relacionar nuestras clases para que aporten una solución a un problema determinado.
Tal y como ocurre con nuestras clases, los patrones de diseño son la respuesta, fruto de la experiencia, frente al tipo de problemas recurrentes en la creación de software orientado a objetos. Probados y testados.
Uno de los múltiples patrones de diseño existentes es el denominado Singleton. Su finalidad es la de proporcionar una única instancia de una clase determinada, compartida a lo largo y ancho de nuestra aplicación.
Por lo general se utiliza el patrón Singleton con aquellos objetos que sean muy costosos en cuanto a recursos utilizados (por ejemplo memoria, procesador o E/S, entre otros) o bien porque sencillamente no es preciso generar más de una instancia de objeto a partir de una clase determinada para su uso común por parte de toda la aplicación en la que se presenta.
Un ejemplo evidente en el uso de este tipo de patrón en nuestras aplicaciones Xojo es el objeto App que empleamos en nuestros proyectos. Otro ejemplo podría ser fácilmente el de un único objeto Singleton para la gestión de las preferencias de nuestra aplicación o bien el que aporte acceso a una base de datos, ya sea remota o local. En cualquiera de estos casos, no tendría mucho sentido contar con varias instancias dando vueltas por ahí… ¿verdad? ¡Incluso podría llegar a resultar un problema si no fuese así! Imagina, por ejemplo varias instancias creadas a partir de una clase encargada de utilizar una base de datos, ¿imaginas la cantidad de problemas que podría causar?
Patrón Singleton en la práctica
Para llevar a la práctica en Xojo una clase que actúe como Singleton, es decir en la que se utilice la única misma instancia en todos los casos, necesitamos utilizar los siguientes ingredientes:
- Un constructor cuyo ámbito (scope) esté definido como Privado, de esta forma nos aseguramos que el cliente (usuario) de la clase no pueda generar nuevas instancias utilizando las opciones habituales del tipo:
dim miInstancia as Clase = new Clase dim miInstancias as new Clase
- Un método compartido (denominado método estático o método de clase en otros lenguajes de programación). Este será el punto de entrada que utilice el cliente de la clase para recuperar la única instancia disponible.
- Una propiedad compartida cuyo ámbito esté definido como Privado y que será la responsable de contener (apuntar a) la única instancia compartida… ¡de la propia clase!
Teniendo en cuenta que estos son los tres elementos básicos para crear un Singleton en Xojo, veamos mediante un ejemplo simple como ponerlo en marcha. Para ello crearemos una clase “Saludador” que se limite a presentar el clásico mensaje de “Hola mundo”, indicando además cuántas veces ha sido invocada. No es que se trate del mejor de los escenarios en los que puede actuar un Singleton, pero al reducir al máximo su funcionalidad creo que será también más sencillo comprenderlo.
Si tienes dudas sobre términos como clases, instancias, métodos o propiedades compartidos… recuerda que esto y mucho más es lo que te explico, desde cero, sin necesidad de conocimientos previos en programación, en el libro “Programación Multiplataforma Xojo”.
El “Saludador” Singleton
Empezaremos nuestro proyecto creando una nueva Clase. Para ello utiliza Insert > Class. A continuación, utiliza el panel Inspector para asignar “Saludador” como nombre de la clase.
Con la clase recién creada seleccionada, añade una nueva propiedad (Insert > Property). Utiliza “contador” para el campo ‘Name’ y define su tipo (‘Type’) como Integer. Esta será la propiedad encargada de llevar la cuenta de los saludos.
Seguidamente añadiremos a la clase un nuevo método (Insert > Method). Este será el encargado de proporcionar la funcionalidad a nuestra clase Singleton. Utiliza “Saluda” en el campo ‘Method Name’ y mantén su visibilidad (Scope) como público. A continuación introduce el siguiente código asociado al método recién creado:
MsgBox "¡Hola mundo!" + EndOfLine + EndOfLine +"Con esta, ya he saludado " + contador.totext + " veces." contador = contador + 1
Una vez creados los elementos que aportan la funcionalidad a la clase, es el momento de incorporar los responsables de convertirla en un Singleton.
Para ello empezaremos añadiendo la propiedad compartida encargada de contener la única instancia de la clase que se utilizará a lo largo y ancho de la aplicación. Utiliza Insert > Shared Property. Selecciónala y, en el panel Inspector, utiliza “sharedObject” en el campo ‘Name’ y define su tipo a ‘Saludador’; es decir, el mismo tipo de la clase que estamos definiendo.
Ahora es el momento de crear el Constructor de nuestra clase. Recuerda que se trata del método especial que ejecuta cada clase cada vez que se quiere crear una nueva instancia (objeto) a partir de la misma. Utiliza Insert > Method. En el panel Inspector introduce “constructor” en el campo ‘Method Name’ (también puedes seleccionarlo en el menú asociado), y asegúrate de definir su visibilidad (scope) a Privado. Con ello nos aseguramos de que nadie pueda crear nuevas instancias a partir de la clase. Para que en nuestro ejemplo podamos ver la ejecución del constructor en acción, nos encargaremos de iniciar la propiedad “Contador” con el valor “1”.
Por último incorporamos el método que supone el punto de entrada para que el resto de nuestra aplicación pueda recuperar la única instancia compartida disponible de la clase. Utiliza Insert > Shared Method y en el panel Inspector resultante utiliza “getSaludador” en el campo ‘Method Name’, asegurándote de indicar en el Tipo Devuelto (Return Type) que se encarga de devolver un objeto del tipo ‘Saludador’ como resultado de su invocación.
En el Editor de Código asociado al método recién creado “getSaludador”, introduce las siguientes líneas:
if sharedObject is nil then sharedObject = new Saludador end Return sharedObject
Como puedes obvservar, es bastante fácil de seguir. En primer lugar vemos si la propiedad responsable de contener la instancia compartida aun no ha sido iniciada (en cuyo caso apuntará a ‘Nil’) y, si es así, nos encargamos de crear desde dentro de la clase la única instancia que compartiremos con el resto de la aplicación, asignándola a la propiedad.
¡Aquí es donde reside la parte de la magia! Al marcar el método Constructor como Privado nos aseguramos de que la propia clase será la única que pueda llamar a dicho método y, por tanto, crear nuevas instancias de la clase.
Utiliza el Singleton
Con nuestra clase Singleton ya creada, añade un nuevo evento ‘Open’ a la ventana Window1 (utilizaremos un proyecto de tipo Desktop para nuestro ejemplo, si bien el principio OOP es aplicable al resto de las plataformas soportadas). Introduce las siguientes líneas de código en el Editor de Código resultante:
dim miSaludador as Saludador = Saludador.getSaludador miSaludador.saluda dim miOtroSaludador as Saludador = Saludador.getSaludador miOtroSaludador.saluda
Como puedes observar, en ningún momento se crean nuevas instancias de la clase sino que se utiliza el método Público propuesto para recuperar la única instancia compartida de la misma. Como prueba, intenta crear una nueva instancia de la clase… y verás que el compilador de Xojo te presentará un error.
Una vez hemos recuperado la instancia compartida en dos variables distintas, también comprobamos mediante este sencillo ejemplo que podemos invocar los métodos públicos disponibles (funcionalidad de la clase).
Conclusiones
Aunque se trata de un ejemplo súmamente sencillo, espero que este artículo haya servido para dar a conocer el patrón de diseño Singleton, como podemos utilizarlo en Xojo y que te haya abierto las puertas a su implementación en tus propios proyectos.
[…] *Read this post in Spanish […]
[…] anteriores entradas hemos visto cómo implementar el patrón de diseño Singleton y también de qué modo tan práctico encontramos el patrón de diseño Observer implementado en […]