Tabla de contenido:
- Paso 1: Cree su clase, con archivo de encabezado y archivo CPP
- Paso 2: establezca el constructor en privado
- Paso 3: establece el destructor en privado
- Paso 4: creación de una variable de puntero estático en el singleton
- Paso 5: creación de una función de instancia
- Paso 6: creación de funciones públicas estáticas
- Paso 7: creación de la función de terminación
- Paso 8: Establecer PtrInstance en Nullptr
- Paso 9: prueba y conclusión
Video: Cómo hacer el patrón de diseño Singleton en C ++: 9 pasos
2024 Autor: John Day | [email protected]. Última modificación: 2024-01-30 08:42
Introducción:
El propósito de esta guía de instrucciones es enseñar al usuario cómo implementar el patrón de diseño singleton en su programa C ++. Al hacerlo, este conjunto de instrucciones también explicará al lector por qué los elementos de un singleton son como son y cómo se procesa el código. Saber esto le ayudará en el futuro a depurar sus futuros singleton. ¿Qué es el patrón de diseño singleton? El patrón de diseño singleton es un patrón de diseño en el que el codificador crea una clase de la que solo se puede crear una instancia una vez; básicamente, se puede acceder a las funciones públicas de las clases en cualquier lugar, siempre que haya # incluido el archivo de encabezado en otros archivos relacionados con el proyecto.
El patrón de diseño singleton es un patrón de diseño imprescindible para cualquier programador orientado a objetos, programadores de software y programadores de juegos. El patrón de diseño singleton también es uno de los patrones de diseño de codificación más fáciles que existen. Aprenderlo puede ayudarlo a aprender otros patrones de diseño más difíciles en el futuro. También puede ayudarlo a optimizar el código de su programa de formas que no creía que fueran posibles.
Si bien la dificultad del patrón de diseño singleton es fácil en comparación con otros patrones de diseño, este conjunto de instrucciones tiene una dificultad media. Esto significa que para seguir estas instrucciones, le recomendamos que conozca los requisitos de sintaxis básicos y avanzados de C ++. También debe conocer la etiqueta de codificación C ++ adecuada (es decir, mantener privadas las variables de clase, una clase por archivo de encabezado, etc.). También debe saber cómo liberar memoria y cómo funcionan los constructores y destructores en C ++.
Esta guía instructiva le llevará en promedio alrededor de 10 a 15 minutos.
Requerimientos materiales:
-Una computadora (puede ser PC o Mac) capaz de ejecutar Visual Studios (cualquier versión)
-Un programa simple, creado en Visual Studios, con el que puedes probar tu singleton
Nota: El patrón de diseño singleton se puede realizar en cualquier otro IDE o interfaz de codificación compatible con C ++, pero para este conjunto de instrucciones, usaremos Visual Studios Enterprise Edition.
Paso 1: Cree su clase, con archivo de encabezado y archivo CPP
Para crear estos dos archivos y la clase a la vez, abra su proyecto / programa en Visual Studios, vaya al explorador de soluciones, haga clic derecho y debería aparecer un cuadro cerca del cursor del mouse, busque la opción "Agregar", coloque el cursor sobre sobre él, y debería aparecer otro cuadro a la derecha. En este cuadro, desea encontrar la opción "Nuevo elemento …", haga clic en ella y debería aparecer una ventana, similar a la imagen de la foto 1.1 a continuación. En esta ventana, debe seleccionar "Clase C ++" y luego presionar "Agregar". Esto abrirá otra ventana que se parece a la imagen de la foto 1.2. En esta ventana, escribe el nombre de su clase en el campo "Nombre de la clase" y Visual Studios nombrará automáticamente el archivo real después del nombre de la clase. Para el propósito de esta instrucción, vamos a nombrar nuestra clase "EngineDebugSingleton", pero puede ser cualquier nombre basado en letras. Ahora puede presionar "Aceptar" y continuar con el paso 2.
Nota: El explorador de soluciones y el lugar donde se guardan los archivos en su computadora están separados. Mover o crear algo en el explorador de soluciones no moverá ni organizará los archivos dentro del explorador de archivos de su sistema operativo. Una forma segura de organizar sus archivos en el lado del explorador de archivos sería eliminar, pero no eliminar los archivos específicos del explorador de soluciones, mover los mismos archivos en el explorador de archivos a la ubicación deseada y luego volver al explorador de soluciones, hacer clic con el botón derecho, busque la opción "Agregar", luego busque "Elemento existente" y busque los archivos que movió. Asegúrese de mover tanto el encabezado como el archivo cpp.
Paso 2: establezca el constructor en privado
Con su archivo CPP recién creado y el archivo de encabezado, si no se abrió automáticamente cuando lo creó, vaya al explorador de soluciones y haga clic y abra "EngineDebugSingleton.h". Luego será recibido con un "EngineDebugSingleton ()", el constructor predeterminado de la clase y "~ EngineDebugSingleton ()" el destructor de la clase. Para este paso, querremos configurar el constructor como privado, esto significa que esta función solo está disponible para la clase y nada más. Con esto, no podrá crear una variable o asignar la clase a la memoria fuera de la clase, solo en el archivo de encabezado de las clases y las otras funciones de las clases. Tener el constructor privado es clave para el patrón de diseño y cómo operan los singleton. Descubriremos en pasos futuros cómo se crea una instancia y se accede a un singleton.
La clase ahora debería verse así después de mover el constructor a privado (mira la foto asociada)
Paso 3: establece el destructor en privado
Como hicimos con el constructor en
paso 2, para este paso, ahora configuraremos el destructor como privado. Al igual que con el constructor, nada, excepto la propia clase, podrá eliminar de la memoria cualquier variable de la clase.
La clase ahora debería verse así después de completar este paso. (Ver foto asociada)
Paso 4: creación de una variable de puntero estático en el singleton
En este paso, crearemos un
variable de puntero estático de tipo “EngineDebugSingleton *”. Esta será la variable que se utilizará para asignar nuestro singleton a la memoria y apuntará a ella durante todo el tiempo que nuestro singleton esté asignado a la memoria.
Así es como debería verse nuestro archivo de encabezado después de crear esta variable
Paso 5: creación de una función de instancia
Ahora queremos hacer una instancia.
función. La función necesitará ser una función estática y querrá devolver una referencia a nuestra clase (“EngineDebugSingleton &”). Llamamos a nuestra función Instance (). En la función en sí, primero querremos probar si ptrInstance == nullptr (se puede abreviar a! PtrInstance), si es nullptr, esto significa que el singleton no ha sido asignado y en el alcance de la instrucción if, lo haremos desea asignar haciendo ptrInstance = new EngineDebugSingleton (). Aquí es donde realmente asigna el singleton a la memoria. Después de salir del alcance de la instrucción if, devolveremos a qué apunta ptrInstance, que se indica con la sintaxis “* ptrInstance”. Usaremos esta función en gran medida al hacer nuestras funciones públicas estáticas, por lo que podemos verificar si el singleton se ha creado y asignado a la memoria. En esencia, esta función hace que pueda tener solo una asignación de la clase y no más.
Así es como debería verse nuestra clase ahora después de crear la función Instance (). Como puede ver, todo lo que hemos hecho se ha quedado en la sección privada de la clase, esto va a cambiar un poco en los próximos pasos.
Paso 6: creación de funciones públicas estáticas
Una vez que haya creado la función de
Paso 5, puede comenzar a realizar funciones públicas estáticas. Cada función pública debe tener una función privada que la acompañe, el nombre de esta función no puede ser el mismo. ¿Por qué hacer que la función sea estática? Estamos haciendo estáticas las funciones públicas para que se pueda acceder a ellas sin un objeto real. Entonces, en lugar de hacer algo como “EngineDebugSingleObj-> SomeFunction ()”, hacemos “EngineDebugSingleton:: Some Function ()”. Esto hace posible que se pueda acceder a un singleton básicamente en cualquier lugar del código, siempre que haya # incluido el archivo de encabezado en el archivo de proyecto específico con el que está trabajando. Con esto, también puede crear el singleton a través de cualquiera de sus funciones públicas.
Para nuestros propósitos en este paso, creamos dos funciones vacías estáticas públicas, “sumar ()” y “restar ()”. En la sección privada, tenemos dos funciones más, “PrivAdd ()” y “PrivSubtract ()”. También agregamos una variable int llamada "NumberOfThings". La definición de estas funciones irá al archivo CPP de nuestras clases. Para hacer que la función entre fácilmente en el archivo CPP, resalte, con el cursor, la función, que debe tener una línea verde debajo, y presione “ALT Izquierda + ENTER”, le dará la opción de crear la definición en el archivo CPP asociado a las clases. Consulte la Foto 6.1 para ver cómo debería verse el archivo de encabezado y, una vez que haya creado todas las definiciones de funciones, su CPP debería verse como la Foto 6.2, excepto que las definiciones de sus funciones no tendrán código.
Ahora querrá agregar el mismo código que en la Foto 6.2 en sus definiciones de función. Como se indicó anteriormente, nuestras funciones públicas harán uso de la función Instance (), que devolverá a lo que apunta ptrInstance. Esto nos permite acceder a las funciones privadas de nuestra clase. Con cualquier función pública de singleton, solo debería llamar a esa función de instancia. La única excepción a esto es nuestra función Terminar.
Nota: Las funciones públicas y privadas exactas que se muestran en este paso no son necesarias, puede tener diferentes nombres de función y operaciones en la función privada, pero para cualquier tipo de función pública, debe tener una función privada que la acompañe y la función pública siempre debería usar, en nuestro caso, la función Instance ().
Paso 7: creación de la función de terminación
Dado que solo podemos desasignar nuestro singleton de la memoria en nuestra clase, debemos crear una función pública estática. Esta función llamará a delete en ptrInstance, que llama al destructor de clases y luego querremos volver a establecer ptrInstance en nullptr para que pueda ser asignado nuevamente si su programa no termina. También querrá terminar sus Singleton para limpiar cualquier memoria asignada que haya asignado en las variables privadas de cualquier Singleton.
Paso 8: Establecer PtrInstance en Nullptr
Para completar su singleton, desea dirigirse al archivo EngineDebugSingleton. CPP y en la parte superior del archivo CPP, en nuestra instancia, escriba "EngineDebugSingleton * EngineDebugSingleton:: ptrInstance = nullptr".
Hacer esto establecerá inicialmente ptrInstance en nullptr, por lo que cuando revise la función de instancia por primera vez, se permitirá que nuestra clase se asigne a la memoria. Sin él, lo más probable es que obtenga un error porque intentará acceder a la memoria que no tiene nada asignado.
Paso 9: prueba y conclusión
Ahora querremos probar que nuestro singleton para asegurarnos de que funciona, esto implicará que llamemos a las funciones públicas como se describe en el paso 6 y le recomendamos que configure puntos de interrupción para recorrer su código y ver que el singleton está funcionando como debería ser. Nuestro punto de partida estará en el main.cpp de nuestro proyecto y nuestro main.cpp ahora se parece a la imagen de abajo.
¡Felicidades! Acaba de completar su primera implementación del patrón de diseño Singleton. Con este patrón de diseño, ahora puede optimizar su código de varias formas. Por ejemplo, ahora puede crear sistemas de administración que operen durante el tiempo de ejecución de su programa, a los que se puede acceder a través de funciones estáticas en cualquier lugar donde haya incluido la clase.
Su archivo de encabezado final debe verse como la foto 7.1. El archivo CPP asociado de su singleton debe verse como la foto 6.2 con la adición, en la parte superior del archivo, del código que se muestra en el paso 8. Esta instrucción le proporcionó una estructura simple del patrón de diseño Singleton.
Consejos para la resolución de problemas:
¿Tiene errores relacionados con la memoria?
Asegúrese de consultar el paso 7 y el paso 8 para asegurarse de que está configurando ptrInstance en nullptr.
¿Ocurre un bucle infinito?
Asegúrese de que para las funciones públicas, en sus definiciones, está llamando a la función privada, no a la misma función pública.
¿Objetos asignados dentro del singleton que causan pérdidas de memoria?
Asegúrese de llamar a la función de terminación de su singleton cuando sea apropiado dentro de su código de programa, y en el destructor de su singleton, asegúrese de desasignar cualquier objeto que haya sido asignado a la memoria dentro del alcance del código singleton.