Como Usar el Patrón de Diseño “Factory Method” o Método Factory en PHP 8
En esta página:
Con las nuevas versiones de PHP podemos crea lógicas más profesionales dentro de nuestro código, cuando digo lógica, me refiero a cierta forma o método de escribir código. Uno de estos métodos es el “Factory Method” o método Factory, asi se ve más práctico, a pesar que si traducimos las palabras Factory Method significan “Método de fábrica”. El Factory Method es un patrón de diseño que nos permite optimizar nuestro proyecto. En este Post te enseñare a Como Usar el Patrón de Diseño “Factory Method” o Método Factory en PHP 8, vamos con ello.
Antes de continuar te invito a leer los siguientes artículos:
- Que es PHP y otros detalles
- Como Usar Try y Catch en PHP
- Porque el Operador === es más Rápido que el Operador == en PHP
- Convertir nuestros registros MySQL a JSON con PHP
- Protección de Contraseñas con Argon2 en PHP 7
- Crear un sitemap dinámico con PHP y MySQL (Corregido 29-07-2019)
- Buenas Prácticas para PHP en 2020
- Lee más artículos en la categoría PHP
Asimismo, te invito a escuchar el Podcast: “5 Consejos para ser un Programador más Productivo” (No son los clásicos consejos técnicos de programación, si no de rutinas y buenos hábitos cotidianos) y “Qué Es NoCode Development” (Anchor Podcast):
Spotify: | Sound Cloud: | Apple Podcasts | Anchor Podcasts |
Bien ahora continuemos con el Post: Como Usar el Patrón de Diseño “Factory Method” o Método Factory en PHP 8.
Digamos que tenemos una clase de carrito de compras llamada modeloCarrito() y esa clase contiene métodos para almacenar en caché RedisDB y en MySQL, los datos del carrito de compra y conservarlos durante mucho tiempo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class modeloCarrito { public array $datos; // Mejor toma esta configuración de un archivo especial o variables env // Pero este artículo no trata sobre el almacenamiento de configuraciones private array $configuracionRedis = [ 'user' => 'usuario', 'password' => 'password' ]; private array $configuracionMysql = [ 'hostname' => 'localhost', 'login' => 'usuario23', 'password' => '123456', 'database' => 'mibasededatos' ]; // Necesitamos implementar un método de almacenamiento en caché RedisDB y otro para MySQL // Redis DB es más adecuado para esto public function cache(): void { // Acá va el código } public function save(): void { // Acá va el código } } |
Aquí está una clase en blanco, ahora necesitamos implementar estos métodos. De hecho, el objetivo de cada uno de ellos es conectarse a la base de datos deseada y almacenar en ella datos del carrito de comprar. Gracias al patrón de diseño Factory Method, moveremos el código común (guardado) para todas las clases que trabajan con bases de datos a una clase abstracta. Y la funcionalidad asociada a la conexión será diferente para cada base de datos, por lo que la sacaremos por separado utilizando la interfaz común.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
abstract class AbstractDataBaseFactory { // Un método directo de Factory que permite que las subclases regresen // cualquier conector concreto de la interfaz deseada, ya que se hace abstracto // Crearemos la interfaz más adelante abstract public function getDataBase(): DataBaseConnector; // Este método será el mismo para todas las bases de datos public function save(array $data): void { $database = $this->getDataBase(); $database->connect(); $database->save($data); $database->disconnect(); } } |
Implementemos una clase concreta para RedisDB.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class RedisFactory extends AbstractDataBaseFactory { // PHP 8 te permite agregar campos privados de inicio de sesión y contraseña usando el constructor public function __construct(private readonly string $login, private readonly string $password) {} // Implementación de Factory Method de Concreto // Devuelve una instancia de la clase de conector que implementa la interfaz DataBaseConnector public function getDataBase(): DataBaseConnector { return new RedisConnector($this->login, $this->password); } } |
De la misma manera creamos una clase para la base de datos MySql.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class MysqlFactory extends AbstractDataBaseFactory { // A diferencia de Redis, necesitaremos un array de datos para conectarnos public function __construct(private readonly array $settings) {} // // Implementación del Factory Method en Concreto public function getDataBase(): DataBaseConnector { return new MysqlConnection($this->settings); } } |
Es con estas clases de base de datos que acabamos de crear que funcionará nuestro carrito de compras. Pero la interfaz de los conectores aún no está escrita. Necesitaremos métodos para conectarse a la base de datos, desconectarse y, por supuesto, guardar datos. En el futuro, será posible ampliar la interfaz con varios métodos, pero por ahora esto es suficiente.
1 2 3 4 5 6 7 8 |
interface DataBaseConnector { public function connect(); public function disconnect(); public function save(array $data): void; } |
No describiré las implementaciones de los conectores RedisDB, todo se puede implementar allí de manera bastante estándar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class RedisConnector implements DataBaseConnector { public function __construct(private $login, private $password) {} /** * @throws Exception */ public function connect(): void { // Acá va el código para conectar } public function disconnect() { // Acá va el código para desconectar } public function save(array $data): void { // Acá va el código para guardar } } |
Igualmente para MySQL, todo se puede implementar allí de manera bastante estándar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class MysqlConnection implements DataBaseConnector { public function __construct(private $settings) {} public function connect() { // Acá va el código para conectar } public function disconnect() { // Acá va el código para desconectar } public function save(array $data): void { // Acá va el código para guardar } } |
Todo está listo para ser utilizado en los métodos de nuestra clase modeloCarrito():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class modeloCarrito { public array $datos; // Mejor toma esta configuración de un archivo especial o variables env // Pero este artículo no trata sobre el almacenamiento de configuraciones private array $configuracionRedis = [ 'user' => 'usuario', 'password' => 'password' ]; private array $configuracionMysql = [ 'hostname' => 'localhost', 'login' => 'usuario23', 'password' => '123456', 'database' => 'mibasededatos' ]; // Necesitamos implementar un método de almacenamiento en caché // Redis DB es más adecuado para esto public function cache(): void { try { $redis = new RedisFactory($this->configuracionRedis['user'], $this->configuracionRedis['password']); $redis->save($this->data); } catch (\Exception $e) { //... } } // Acá almacenamos en MySQL public function save(): void { try { $mysql = new MysqlFactory($this->configuracionMysql); $mysql->save($this->data); } catch (\Exception $e) { //... } } } |
Puedes ver en el método cache() y save() hacemos uso de try – catch para usar nuestros métodos Factory creados anteriormete.
Gracias al uso del patrón de diseño Factory Method podemos acceder a diversas bases de datos dentro de modelos como un carrito de compra sin preocuparnos de las tareas: conexión, guardado, formateo de datos, desconexión, etc. Evitamos la duplicación de código, la carga excesiva en métodos y clases.
Conclusión
En este Post hemos aprendido a trabajar con el Patrón de Diseño “Factory Method” o Método Factory en PHP. Al principio te puede parecer confuso, pero conforme lo uses en tus proyectos, lograrás comprenderlo y dominarlo. Recuerda que la práctica hace al maestro.
Nota(s)
- No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo.
Síguenos en las Redes Sociales para que no te pierdas nuestros próximos contenidos.
- PHP
- 18-09-2022
- 19-09-2022
- Crear un Post - Eventos Devs - Foro
Social
Redes Sociales (Developers)
Redes Sociales (Digital)