Patrones de diseño con Flutter: 2— Prototype

Paolo Pinto
4 min readApr 12, 2024

--

Cuando estaba aburrido me puse a pensar el como lanzan tantos celulares “chinos” en poco tiempo. Esto claro debía ser automatizado de alguna forma ¿verdad?, eso me llevo a curiosear. La pregunta fue ¿Las empresas tendrán alguna receta o molde para crear solo las partes que se repiten?

Cuando aprendemos POO nos enseñan el concepto de herencia, cuando creas el objeto auto y luego los modelos de autos. Este patron surge del problema de cuando tienes un objeto y quieres crear una copia exacta de él. ¿Cómo lo harías?

En primer lugar, debes crear un nuevo objeto de la misma clase. Después debes recorrer todos los campos del objeto original y copiar sus valores en el nuevo objeto.

fuente: refactoring.guru

¡Bien! Pero hay una trampa. No todos los objetos se pueden copiar de este modo, porque algunos de los campos del objeto pueden ser privados e invisibles desde fuera del propio objeto.

¿Qué se puede hacer con el patrón Prototype?

Esta interfaz contiene un método de clonación que copia todos los valores de campo del objeto original al nuevo, incluidos los campos privados. Los objetos que los implementan ofrecen una alternativa eficiente a la creación de subclases, especialmente útil en objetos con múltiples campos y configuraciones.

diagrama de clases

En el siguiente ejemplo observamos el caso de uso con una clase Forma(Shape) que se utiliza como prototipo para crear las clases Circulo(circle) y Rectángulo(Rectangle).

1. Formas

En el siguiente ejemplo observamos el caso de uso con una clase Forma(Shape) que se utiliza como prototipo para crear las clases Circulo(circle) y Rectángulo(Rectangle)

diagrama de clases para el ejemplo
  1. Primero definimos la clase Shape(Forma).
import 'package:flutter/material.dart';
abstract class Shape {
Shape(this.color);
Shape.clone(Shape source) : color = source.color;
Color color;
Shape clone();
void randomiseProperties();
Widget render();
}

Antes de pasar a las clases Rectangulo y Circulo es importante mencionar que utilizaremos el package faker de flutter para ayudarnos con el metodo randomiseProperties() o propiedades aleatorias.

2. Implementamos Circulo

import 'package:faker/faker.dart';
import 'package:flutter/material.dart';
import '../shape.dart';
class Circle extends Shape {
Circle(super.color, this.radius);
Circle.initial([super.color = Colors.black]) : radius = 50.0;
Circle.clone(Circle super.source)
: radius = source.radius,
super.clone();
double radius;
@override
Shape clone() => Circle.clone(this);
@override
void randomiseProperties() {
color = Color.fromRGBO(
random.integer(255),
random.integer(255),
random.integer(255),
1.0,
);
radius = random.integer(50, min: 25).toDouble();
}
@override
Widget render() {
return SizedBox(
height: 120.0,
child: Center(
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
height: 2 * radius,
width: 2 * radius,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
child: const Icon(
Icons.star,
color: Colors.white,
),
),
),
);
}
}

3. Implementamos Rectangulo

import 'package:faker/faker.dart';
import 'package:flutter/material.dart';
import '../shape.dart';
class Rectangle extends Shape {
Rectangle(super.color, this.height, this.width);
Rectangle.initial([super.color = Colors.black])
: height = 100.0,
width = 100.0;
Rectangle.clone(Rectangle super.source)
: height = source.height,
width = source.width,
super.clone();
double height;
double width;
@override
Shape clone() => Rectangle.clone(this);
@override
void randomiseProperties() {
color = Color.fromRGBO(
random.integer(255),
random.integer(255),
random.integer(255),
1.0,
);
height = random.integer(100, min: 50).toDouble();
width = random.integer(100, min: 50).toDouble();
}
@override
Widget render() {
return SizedBox(
height: 120.0,
child: Center(
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
height: height,
width: width,
decoration: BoxDecoration(
color: color,
),
child: const Icon(
Icons.star,
color: Colors.white,
),
),
),
);
}
}

4. mostramos en una vista basica

import 'package:flutter/material.dart';
import '../../../constants/constants.dart';
import '../../../design_patterns/prototype/prototype.dart';
class PrototypeExample extends StatefulWidget {
const PrototypeExample();
@override
_PrototypeExampleState createState() => _PrototypeExampleState();
}
class _PrototypeExampleState extends State<PrototypeExample> {
final _circle = Circle.initial();
final _rectangle = Rectangle.initial();
@override
Widget build(BuildContext context) {
return ScrollConfiguration(
behavior: const ScrollBehavior(),
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(
horizontal: LayoutConstants.paddingL,
),
child: Column(
children: <Widget>[
_circle.render(),
const Divider(),
_rectangle.render()
],
),
),
);
}
}

Happy Coding!

Otros articulos 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

--

--