Patrón Strategy
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 93 de 110.
El patrón Strategy te permite definir una familia de algoritmos, encapsular cada uno en su propia clase y hacer que sean intercambiables en tiempo de ejecución. En lugar de codificar el comportamiento directamente en una clase, inyectas el comportamiento mediante una interfaz, lo que te permite cambiar de estrategia sin modificar la clase que las utiliza.
Considere un sistema de pago en el que desee admitir diferentes métodos de pago. En lugar de utilizar condicionales para manejar cada método, se define una interfaz de estrategia y se crean implementaciones concretas:
abstract class PaymentStrategy {
void pay(double amount);
}
class CreditCardPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$$amount with Credit Card');
}
class PayPalPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$$amount with PayPal');
}
class ShoppingCart {
PaymentStrategy _paymentStrategy;
ShoppingCart(this._paymentStrategy);
void setPaymentStrategy(PaymentStrategy strategy) {
_paymentStrategy = strategy;
}
void checkout(double total) {
_paymentStrategy.pay(total);
}
}
void main() {
var cart = ShoppingCart(CreditCardPayment());
cart.checkout(99.99); // Paid $99.99 with Credit Card
cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99); // Paid $49.99 with PayPal
}El ShoppingCart no sabe ni le importa cómo funciona el pago; simplemente delega en cualquier estrategia que esté configurada actualmente. Puedes añadir nuevos métodos de pago creando nuevas clases de estrategia sin tocar el código del carrito. Este patrón es ideal cuando tienes múltiples formas de realizar una acción y quieres seleccionar o cambiar entre ellas dinámicamente.
Desafío
Fácil¡Construyamos un sistema de formato de texto usando el patrón Strategy! Crearás un sistema en el que se puedan aplicar distintas estrategias de formato al texto, lo que permitirá a los usuarios cambiar entre formatos dinámicamente sin modificar el procesador de texto principal.
Organizarás tu código en dos archivos:
formatting_strategies.dart: Crea aquí tu sistema de estrategias. Define una clase abstractaFormattingStrategycon un métodoString format(String text). Después, implementa tres estrategias concretas:UppercaseStrategy: convierte el texto completamente a mayúsculasLowercaseStrategy: convierte el texto completamente a minúsculasTitleCaseStrategy: escribe en mayúscula la primera letra de cada palabra (separa por espacios, escribe en mayúscula el primer carácter de cada palabra y el resto en minúsculas)
TextProcessorque contenga unaFormattingStrategy. Debe tener un constructor que acepte una estrategia inicial, un métodosetStrategy()para cambiar la estrategia en tiempo de ejecución y un métodoprocess(String text)que aplique la estrategia actual y devuelva el resultado formateado.main.dart: Importa tus estrategias de formato y demuestra cómo el patrón Strategy permite cambiar el comportamiento dinámicamente. Crea unTextProcessorque comience conUppercaseStrategy. Procesa el textohello worlde imprime el resultado. Después, cambia aLowercaseStrategy, procesaHELLO WORLDe imprime el resultado. Por último, cambia aTitleCaseStrategy, procesathe quick brown foxe imprime el resultado.
Esto demuestra el poder del patrón Strategy: tu TextProcessor no necesita conocer los detalles de cómo funciona el formato. Simplemente delega en la estrategia que esté configurada actualmente, lo que facilita añadir nuevas opciones de formato sin modificar el procesador.
Salida esperada:
HELLO WORLD
hello world
The Quick Brown FoxPruébalo tú mismo
import 'formatting_strategies.dart';
void main() {
// TODO: Crear un TextProcessor comenzando con UppercaseStrategy
// TODO: Procesar el texto 'hello world' e imprimir el resultado
// TODO: Cambiar a LowercaseStrategy
// TODO: Procesar 'HELLO WORLD' e imprimir el resultado
// TODO: Cambiar a TitleCaseStrategy
// TODO: Procesar 'the quick brown fox' e imprimir el resultado
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO
Archivos externosLibrerías e importacionesIntroducción a la POOClases vs. ObjetosLa palabra clave thisMétodosVariables de instanciaConceptos básicos de constructoresResumen - Calculadora sencilla4Seguridad de nulos
Introducción a la seguridad de nulosNulables vs No nulablesLos operadores ? y !Palabra clave Late y Null SafetyOperadores Null-awareNull Safety en clasesResumen - Sistema de perfil de usuario7Clases abstractas e interfaces
Clases abstractasMétodos abstractosInterfaces en DartInterfaces implícitasImplementar vs. ExtenderInterfaces múltiplesRepaso - Calculadora de figuras10Colecciones y Genéricos
Visión general de List, Set y MapColecciones con seguridad de tiposClases genéricasMétodos genéricosRestricciones genéricasIterable e IteratorResumen - Almacenamiento genérico2Constructores en Dart
Constructor por defectoConstructores nombradosListas de inicializaciónConstructores constantesConstructores de fábricaConstructores de redireccionamientoResumen - Constructor de formas5Encapsulamiento
Miembros públicos vs. privadosLa convención del prefijo _Privacidad a nivel de libreríaProfundidad en Getters y SettersOcultamiento de informaciónResumen - Registros de estudiantes8Mixins
Introducción a los MixinsCreación de MixinsUso de múltiples MixinsPalabra clave on en MixinsMixin vs HerenciaMixin vs InterfazResumen - Sistema Animal11Métodos especiales
Sobrescritura de toString()Sobrescritura de hashCode y ==Interfaz ComparableMétodo call()Sobrescritura de noSuchMethodResumen - Colección personalizada14Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy3Propiedades de clase
Miembros de instancia vs. estáticosCampos Final y ConstVariables LateMétodos y campos estáticosGetters y SettersResumen - Gestor de cuentas bancarias6Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosLa anotación @overrideLa palabra clave final en clasesConstructores y herenciaResumen - Jerarquía de empleados9Polimorfismo
Fundamentos del polimorfismoPolimorfismo mediante interfacesComprobación de tipos en tiempo de ejecuciónLos operadores is y asPalabra clave covariantResumen - Procesador de pagos12POO Asíncrona
Futures y async/awaitFundamentos de StreamsStream ControllersConstructores asíncronosAsincronía en métodos de claseRepaso - Data Fetcher15Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón RepositoryPractica por tu cuenta: Compilador de Dart online