Patrones de diseño con Flutter: 4— Factory Method

Paolo Pinto
4 min readApr 12, 2024

--

Cuando decidí usar flutter no me imagine las miles de posibilidades que podria hacer con el hecho de que era multiplataforma. En ese proceso quieres tener diferentes vistas(UI) para una app, el proceso se me hizo pesado. Entonces me dije, ¿ Hay alguna forma de que esto se ponga facil?

Imagina! tienes una horno donde vendes pan y lo repartes a todas las tiendas de la manzana. Decides crear tu app porque te fue muy bien ¡Super! Te va muy bien con eso, decides agregar transporte a camion y solo tenias bicicleta en tu app. Puedes mantenerlo con millones de “if” o podrias aprender este patrón.

hombre repartidor de pan

¿ Que se puede hacer con el patron Factory Method?

La teoría de este patrón nos dice que en lugar de llamar a new para construir objetos, se invoque a un método factory. No te preocupes: los objetos se siguen creando a través del operador new, pero se invocan desde el método factory. Los objetos devueltos por el método fábrica a menudo se denominan productos.

Entonces es lo mismo, pero no del todo.

todo lo haces desde un “factory” en lugar del clasico “new”

Ahora puedes sobrescribir el método factory en una subclase y cambiar la clase de los productos creados por el método.

Se te puede presentar que las subclases sólo pueden devolver productos de distintos tipos si dichos productos tienen una clase base o interfaz común. Además, el método factory en la clase base debe tener su tipo de retorno declarado como dicha interfaz.

cuando tienen misma interfaz

¿Como lo implementaremos?

Se nos pueden presentar diferencias cuando implementamos cualquier patron de diseño, este no sera el caso, ya que haremos una implementación del problema inicial que relate en la introducción.

Imagina!, estas trabajando en mcdonalds. Ya esta apunto de acabar tu turno y en la puerta te dicen: “Necesito una app para ios y android, cuanto podrias cobrarme?”.

Puedes aplicar este patron para el diseño de la UI o lenguaje de diseño, ya que IOS trabaja con cuppertino y android oficialmente con Material. En este articulo te mostrare un ejemplo con los botones.

Diagrama de clases — patron factory method
Diagrama de clases problema planteado

Lucen muy similares verdad?, bueno asi deberia verse cada vez que estas implementando este patrón, bastante similar, y esto desde la abstraccion que tenemos como programadores.

Creator: CustomDialog

Solo implementamos aca el metodo show() y el resto lo abstraemos y que las implementaciones serán distintas dependiendo la UI(Android o IOS).

abstract class CustomDialog {
const CustomDialog();

String getTitle();
Widget create(BuildContext context);

Future<void> show(BuildContext context) => showDialog<void>(
context: context,
barrierDismissible: false,
builder: create,
);
}

ConcreteCreatorA: AndroidAlertDialog(version en android).

La implementacion extends nos indica que estamos heredando los metodos de CustomDialog pero ademas debemos implementar las abstracciones.

class AndroidAlertDialog extends CustomDialog {
const AndroidAlertDialog();

@override
String getTitle() => 'Android Alert Dialog';

@override
Widget create(BuildContext context) {
return AlertDialog(
title: Text(getTitle()),
content: const Text('This is the material-style alert dialog!'),
actions: <Widget>[
TextButton(
onPressed: Navigator.of(context).pop,
child: const Text('Close'),
),
],
);
}
}

ConcreteCreatorB: IosAlertDialog(version en ios).

Lo mismo que con el de Android, pero si notas el widget ya no es AlertDialog sino CupertinoAlertDialog(version de IOS).

class IosAlertDialog extends CustomDialog {
const IosAlertDialog();

@override
String getTitle() => 'iOS Alert Dialog';

@override
Widget create(BuildContext context) {
return CupertinoAlertDialog(
title: Text(getTitle()),
content: const Text('This is the cupertino-style alert dialog!'),
actions: <Widget>[
CupertinoButton(
onPressed: Navigator.of(context).pop,
child: const Text('Close'),
),
],
);
}
}

Interface(product): Widget(que ya están implementadas de las clases (widgets) en la libreria de Flutter).

Código Cliente(en cualquier StateFulWidget):

Como puedes ver en la lista de Dialog (customDialogList) tenemos ambas implementaciones pero en el metodo _showCustomDialog con el metodo .show(context); se muestra el dialog sin importar en donde fue implementado.

import './android_alert_dialog.dart';
import './custom_dialog.dart';
import './ios_alert_dialog.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {


return MaterialApp(
title: 'Material App',
theme: ThemeData(
useMaterial3: true
),
home: HomePage()
);
}
}

class HomePage extends StatefulWidget {
const HomePage({super.key});

@override
State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
final List<CustomDialog> _dialogList = [
const AndroidAlertDialog(),
const IosAlertDialog()
];
Future<void> _showCustomDialog(BuildContext context,int index) async {
final selectedDialog = _dialogList[index];
await selectedDialog.show(context);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
),
body:Center(
child: Column(
children: [
ElevatedButton(
onPressed: () => _showCustomDialog(context,0),
child: const Text('Show Dialog Android'),
),
CupertinoButton(
onPressed: () => _showCustomDialog(context,1),
child: const Text('Show Dialog IOS'),
)
],
),
),
);
}
}

Listo! Ya implementaste Factory Method!

Otros artículos para esta serie

Creacionales:

Estructurales:

  • Pronto…

De Comportamiento:

  • Pronto…..

Tu contribución

👏 ¡Presiona el botón de aplaudir a continuación para mostrar tu apoyo y motivarme a escribir mejor!
💬 Deje una respuesta a este artículo brindando sus ideas, comentarios o deseos para la serie.
📢 Comparte este artículo con tus amigos y colegas en las redes sociales.
➕ Sígueme en Medium.
⭐ Ve los ejemplos prácticos desde mi canal en Youtube: Pacha Code

--

--