design-patterns - español - decorator pattern php
Modelo de estrategia V/S Decorator Pattern (5)
Me encontré con dos patrones.
Patrón de estrategia
Decorador
Patrón de estrategia: -
El patrón de estrategia proporciona varios algoritmos que se pueden usar para realizar una operación o tarea particular.
Patrón decorador: -
El patrón decorador agrega cierta funcionalidad al componente.
De hecho, he descubierto que el patrón de estrategia y el patrón de decorador también se pueden usar indistintamente.
Aquí está el enlace: - ¿ Cuándo y cómo se puede aplicar el patrón de estrategia en lugar de un patrón de decorador?
¿Cuál es la diferencia entre Patrón de estrategia y Patrón de decorador?
¿Cuándo se debe usar el Patrón de estrategia y cuándo se debe usar el Patrón de decorador?
Explica la diferencia entre ambos con el mismo ejemplo.
Decorator debe agregar funcionalidad adicional a una instancia de una clase, por lo que se implementa dinámicamente en tiempo de ejecución. Es un patrón de extensiones de comportamiento. Debido a las condiciones prácticas bajo las cuales Subclases está retrocediendo. La estrategia es un patrón en el que diferentes objetos de estrategia comparten la misma función abstracta, el objeto de contexto concreto se puede configurar en tiempo de ejecución con el objeto de estrategia concreto de un conjunto familiar. Como MVC, el controlador es un caso de rol de estrategia, la vista restringe la estructura de datos de salida, mientras que los controladores serán diferentes en el tiempo de ejecución, lo que cambiará dinámicamente los datos de salida de la vista.
El patrón de estrategia le permite cambiar la implementación de algo usado en tiempo de ejecución.
El patrón de decorador le permite aumentar (o agregar) la funcionalidad existente con funcionalidad adicional en tiempo de ejecución.
La diferencia clave está en el cambio frente al aumento
En una de las preguntas a las que se vinculó también se señala que con el patrón de estrategia, el consumidor es consciente de que existen diferentes opciones, mientras que con el patrón de decorador, el consumidor no estaría al tanto de la funcionalidad adicional.
Como ejemplo, imagina que estás escribiendo algo para ordenar una colección de elementos. Entonces usted escribe una interfaz ISortingStrategy
y luego puede implementar varias estrategias diferentes de clasificación: BubbleSortStrategy
, QuickSortStrategy
, RadixSortStrategy
, luego su aplicación, basada en algunos criterios de la lista existente, elige la estrategia más adecuada para usar para ordenar la lista. Entonces, por ejemplo, si la lista tiene menos de 10 elementos, usaremos RadixSortStrategy
; si se han agregado menos de 10 elementos a la lista desde el último orden, usaremos BubbleSortStrategy
contrario, utilizaremos QuickSortStrategy
.
Estamos cambiando el tipo de ordenamiento en tiempo de ejecución (para ser más eficientes en función de cierta información adicional). Este es el patrón de estrategia.
Ahora imagina que alguien nos pide que proporcionemos un registro de la frecuencia con que se usa cada algoritmo de clasificación para hacer un tipo real y para restringir la ordenación a los usuarios administradores. Podemos agregar estas dos funciones al crear un decorador que ISortingStrategy
cualquier ISortingStrategy
. Podríamos crear un decorador que registre que se usó para ordenar algo y el tipo de estrategia de clasificación decorada. Y podríamos agregar otro decorador que verificara si el usuario actual era administrador antes de llamar a la estrategia de clasificación decorada.
Aquí estamos agregando nuevas funcionalidades de cualquier estrategia de clasificación utilizando el decorador, pero no estamos intercambiando la funcionalidad de ordenación de núcleos (utilizamos las diferentes estrategias para cambiar eso)
Aquí hay un ejemplo de cómo podrían verse los decoradores:
public interface ISortingStrategy
{
void Sort(IList<int> listToSort);
}
public class LoggingDecorator : ISortingStrategy
{
private ISortingStrategy decorated;
public LoggingDecorator(ISortingStrategy decorated)
{
this.decorated=decorated;
}
void Sort(IList<int> listToSort)
{
Log("sorting using the strategy: " + decorated.ToString();
decorated.Sort(listToSort);
}
}
public class AuthorisingDecorator : ISortingStrategy
{
private ISortingStrategy decorated;
public AuthorisingDecorator(ISortingStrategy decorated)
{
this.decorated=decorated;
}
void Sort(IList<int> listToSort)
{
if (CurrentUserIsAdministrator())
{
decorated.Sort(listToSort);
}
else
{
throw new UserNotAuthorizedException("Only administrators are allowed to sort");
}
}
}
La estrategia es patrón se utiliza para "encapsular lo que cambia". Le permite definir algoritmos que pueden intercambiarse en tiempo de ejecución. Por ejemplo (ejemplo tomado de Head First Design Patterns):
Digamos que tienes un simulador de pato. Quieres hacer volar tus objetos de pato. Puede usar herencia para esto, pero se vuelve desordenado rápidamente. Algunos patos no pueden volar (por ejemplo, patos de goma). La forma de hacerlo es encapsular lo que cambia, es decir, el comportamiento de la mosca en su propia clase que implementa IFlybehaviour, por ejemplo. Luego puede usar composición en lugar de herencia e inyectar el comportamiento IFly en sus objetos de pato. También podría tener un método que establezca este comportamiento de vuelo para que el comportamiento de vuelo se pueda cambiar en tiempo de ejecución. Este es esencialmente el patrón de estrategia.
El patrón de decorador se usa para agregar funcionalidad a un objeto en tiempo de ejecución. Te permite envolver objetos dentro de objetos. Los decoradores deben tener el mismo supertipo que los objetos que decoran. Esto le permite llamar a un método en el "contenedor externo" y luego puede llamar en cadena a este mismo método a través de las capas de decoradores. Básicamente es un enfoque más flexible que la subclasificación.
En cuanto a cuáles eliges depende del problema que deseas resolver. ¿Desea tener una familia de algoritmos que sean intercambiables en tiempo de ejecución o desea agregar dinámicamente más funcionalidades a un objeto en tiempo de ejecución?
El libro "Head first design patterns" explica esto bastante bien (probablemente mucho mejor que yo) IMO así que vale la pena leerlo si tienes la oportunidad.
Buena suerte.
Todo se reduce a esto: use la estrategia para elegir una pieza de la funcionalidad central. Use Decorator para agregar funcionalidad adicional. La estrategia es la torta que estamos haciendo y decorador son todas las decoraciones bonitas que le estamos agregando.
- Define una familia de algoritmos,
- Encapsula cada algoritmo, y
- Hace que los algoritmos sean intercambiables dentro de esa familia.
Utilice el patrón de estrategia cuando tenga que cambiar el algoritmo dinámicamente en tiempo de ejecución.
El patrón Decorator cambia dinámicamente la funcionalidad de un objeto en tiempo de ejecución sin afectar la funcionalidad existente de los objetos.
Cuándo usar:
- Agregar funcionalidades / responsabilidades adicionales dinámicamente
- Eliminar funcionalidades / responsabilidades dinámicamente
- Evite demasiada subclasificación para agregar responsabilidades adicionales.
Inconvenientes:
- Uso excesivo del principio de Open Closed (Abierto para extensión y Cerrado para modificación). Use esta característica con moderación, donde el código es menos probable que cambie.
- Demasiadas clases pequeñas y agregarán gastos generales de mantenimiento.
Diferencia clave:
La estrategia te permite cambiar las agallas de un objeto. Decorator te permite cambiar la máscara.
Pocas publicaciones más útiles:
Cuándo usar el patrón decorador?
Ejemplo del mundo real del patrón de estrategia
strategy por fuente