Patrones de diseño con Flutter: 11— Chain of Responsibility

Paolo Pinto
4 min readApr 26, 2024

--

también llamado: Cadena de responsabilidad, cadena de mando

Cuando necesitamos de una atención al servicio del cliente, o call center queremos que este nos pueda ayudar pronto. Se nos presentan contratiempo ya que las grabadoras del primero se tardaron en comunicarnos con un operador. Al final logramos solucionarlo ¿Como esta analogía es implementada en Flutter?

Imagina! Tienes una tiendita que vende colchones. Esta tiendita tiene un sistema donde en la autenticacion verificas si es comprador(algunos permisos)o administrador(todos los permisos). Algun desarrollador te advierte sobre la seguridad de la contraseña, y la implementas.

Tiempo despues se te acercan diciendote que debes implementar el acceso directo a compradores. Y otro te dice que no guardes Información en cache sobre esta información.

Notaste que toda esta comprobación debe ser secuencial. El código se vuelve muy difícil de comprender y costoso de mantener.

fuente: refactoring.guru

¿Que nos ofrece el patron Chain of Responsibility para solucionarlo?

Nos permite pasar solicitudes a lo largo de una cadena de manejadores(handlers). Al recibir una solicitud, cada manejador decide si la procesa o si la pasa al siguiente manejador de la cadena.

el manejador decide si la procesa o si se la pasa al siguiente manejador

En estructura de datos, cada manejador tiene una referencia del siguiente. En forma de cola, es decir, FIFO(first in first out).

cadena de manejadores(handlers)

Segun el diagrama de clases, teoricamente se habla de esto.

Handler(interface):


abstract class PackageHandler {
PackageHandler? nextHandler;
final Function(String) log;

PackageHandler(this.log);

void setNextHandler(PackageHandler handler) {
nextHandler = handler;
}

void handlePackage(String package);
}

BaseHandler: Esta clase es opcional. Se maneja el codigo boilerplate(segementos de codigo que no se alteran). En este ejemplo no lo utilizaremos.

ConcreteHandlers:

  • LocalHandler
class LocalHandler extends PackageHandler {
LocalHandler(Function(String) log) : super(log);

@override
void handlePackage(String package) {
if (package == 'Local') {
log('Package handled at the local level');
} else if (nextHandler != null) {
nextHandler!.handlePackage(package);
}
}
}
  • RegionalHandler
class RegionalHandler extends PackageHandler {
RegionalHandler(Function(String) log) : super(log);

@override
void handlePackage(String package) {
if (package == 'Regional') {
log('Package handled at the regional level');
} else if (nextHandler != null) {
nextHandler!.handlePackage(package);
}
}
}
  • NationalHandler
class NationalHandler extends PackageHandler {
NationalHandler(Function(String) log) : super(log);

@override
void handlePackage(String package) {
if (package == 'National') {
log('Package handled at the national level');
} else if (nextHandler != null) {
nextHandler!.handlePackage(package);
}
}
}

Client(Código cliente):
En el siguiente ejemplo nos centraremos en el metodo handlePackages. Lo que hacemos es hacer la conexion entre handlers para la cadena.

Local -> Regional -> Nacional

Y asi simulamos manejar los 3 tipos de paquetes y al presionar el boton nos muestra quien se encargo de nuestro paquete.

import 'package:flutter/material.dart';

import '../../design_paterns/chain_of_responsibility/main.dart';

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

@override
State<ChainPatternPage> createState() => _ChainPatternPageState();
}

class _ChainPatternPageState extends State<ChainPatternPage> {
final List<String> logs = [];

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: logs.length,
itemBuilder: (context, index) {
return Text(logs[index]);
},
),
),
ElevatedButton(
onPressed: handlePackages,
child: const Text('Handle Packages'),
),
],
),
);
}

void handlePackages() {
// Create handlers
var localHandler = LocalHandler(logs.add);
var regionalHandler = RegionalHandler(logs.add);
var nationalHandler = NationalHandler(logs.add);

// Set next handlers
localHandler.setNextHandler(regionalHandler);
regionalHandler.setNextHandler(nationalHandler);

// Handle packages
localHandler.handlePackage('Local');
localHandler.handlePackage('Regional');
localHandler.handlePackage('National');

setState(() {});
}
}

y YA!

Otros articulos para esta serie

Creacionales:

Estructurales:

De Comportamiento:

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

--

--