language agnostic - que - ¿Cuál es la diferencia entre una mezcla y el patrón decorador?
patterns design gof (3)
El patrón de decorador es una extensión dinámica en el tiempo de ejecución de las clases. Forma dinámicamente una relación es-a.
Comencé a preguntarme si estaba complicando demasiado mi API utilizando el Patrón de Decorador después de recibir esta respuesta sobre la diferencia entre una mezcla y una clase abstracta.
Cuando utiliza el patrón decorador, generalmente está encapsulando, en lugar de extender (o mezclar) la clase base. A menudo, haces esto porque quieres usar la funcionalidad de la clase pero quieres envolver las llamadas para que puedas hacer algunos pasos adicionales antes o después de la llamada. Considera un LoggerDecorator
public class LoggerDecorator implements SomeInterface {
private SomeInterface delegate;
public void someMethod() {
LOGGER.debug("someMethod called");
delegate.someMethod();
}
}
No desea exponer realmente al delegado pero desea utilizar su funcionalidad. Por lo tanto, si nos mezclas, extiendes una clase o decoras realmente depende de lo que estés tratando de hacer. ¿Estás extendiendo una clase y agregándole nuevas funcionalidades? ¿O estás envolviendo / decorando la clase?
No estoy seguro de estar de acuerdo con la afirmación de que Decorator se extiende en el tiempo de ejecución. Sé que eso es lo que dice Wikipedia, pero no creo que sea exacto. Yo sugeriría leer la definición de GoF del patrón Decorator. Es una extensión dinámica, sí, pero ciertamente no tiene que ser en tiempo de ejecución.
Un mixin es apto cuando estás agregando algún comportamiento a tu clase. por ejemplo, la capacidad de enumerar en el caso de un tipo de colección. Puede mezclar tantos conjuntos de comportamientos en su clase como desee. Es una buena manera de reutilizar el código común; Básicamente obtienes un montón de métodos gratis.
Por otro lado, un decorador es más un interceptor astuto. Expone la misma interfaz pública que el objeto de destino, contiene un objeto de destino al que delega todas las llamadas de clientes; sin embargo, decora la llamada con algún procesamiento previo o posterior. por ejemplo, si estoy escribiendo un código en una colección MyCollection y deseo que todas las llamadas a este tipo se registren. Podría derivar un nuevo decorador MyCollectionWithTimeStampedLogging, ambos derivados de una base de ICollection para que se vean idénticos al cliente. El decorador tomaría una instancia de ICollection como un parámetro de ctor y delegaría las llamadas a él. por ejemplo, Add se vería así
public void Add( int item)
{
_logger.log(String.Format( "{0} Add called with param {1}", DateTime.Now, item.ToString());
_collection.Add(item);
_logger.log(String.Format( "{0} Add completed with param {1}", DateTime.Now, item.ToString());
}