design patterns - metodo - ¿Cuál es la diferencia entre el método de plantilla y los patrones de estrategia?
patron visitor explicacion (16)
Patrón de diseño de estrategia
- Admite composición
- Le brinda la flexibilidad de cambiar el comportamiento del objeto en tiempo de ejecución.
- Menos acoplamiento entre el código del cliente y el código de solución / algoritmo.
Patrón de diseño de método de plantilla
- Favorece la herencia sobre la composición
- Definir algoritmo en tu clase base. Las piezas individuales de algoritmo se pueden personalizar en clases para niños.
¿Puede alguien explicarme por favor cuál es la diferencia entre el patrón del método de la plantilla y el patrón de la estrategia?
Hasta donde puedo decir, son 99% iguales, la única diferencia es que el patrón de método de plantilla tiene una clase abstracta como clase base, mientras que la clase de estrategia usa una interfaz que implementa cada clase de estrategia concreta.
Sin embargo, en lo que respecta al cliente , se consumen exactamente de la misma manera: ¿es correcto?
Patrón de plantilla:
El método de plantilla consiste en dejar que las subclases redefinan ciertos pasos del algoritmo, sin cambiar la estructura principal y los pasos del algoritmo, definidos en la clase base. El patrón de plantilla generalmente usa herencia, por lo que se puede proporcionar una implementación genérica de algoritmos en la clase base, que la subclase puede elegir anular si es necesario.
public abstract class RobotTemplate {
/* This method can be overridden by a subclass if required */
public void start() {
System.out.println("Starting....");
}
/* This method can be overridden by a subclass if required */
public void getParts() {
System.out.println("Getting parts....");
}
/* This method can be overridden by a subclass if required */
public void assemble() {
System.out.println("Assembling....");
}
/* This method can be overridden by a subclass if required */
public void test() {
System.out.println("Testing....");
}
/* This method can be overridden by a subclass if required */
public void stop() {
System.out.println("Stopping....");
}
/*
* Template algorithm method made up of multiple steps, whose structure and
* order of steps will not be changed by subclasses.
*/
public final void go() {
start();
getParts();
assemble();
test();
stop();
}
}
/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
private String name;
public CookieRobot(String n) {
name = n;
}
@Override
public void getParts() {
System.out.println("Getting a flour and sugar....");
}
@Override
public void assemble() {
System.out.println("Baking a cookie....");
}
@Override
public void test() {
System.out.println("Crunching a cookie....");
}
public String getName() {
return name;
}
}
Tenga en cuenta que en el código anterior, los pasos del algoritmo go () siempre serán los mismos, pero las subclases pueden definir una receta diferente para realizar un paso en particular.
Patrón de estrategia:
El patrón de estrategia consiste en dejar que el cliente seleccione la implementación de algoritmos concretos en tiempo de ejecución. Todos los algoritmos son aislados e independientes, pero implementan una interfaz común, y no existe la noción de definir pasos particulares dentro del algoritmo.
/**
* This Strategy interface is implemented by all concrete objects representing an
* algorithm(strategy), which lets us define a family of algorithms.
*/
public interface Logging {
void write(String message);
}
/**
* Concrete strategy class representing a particular algorithm.
*/
public class ConsoleLogging implements Logging {
@Override
public void write(String message) {
System.out.println(message);
}
}
/**
* Concrete strategy class representing a particular algorithm.
*/
public class FileLogging implements Logging {
private final File toWrite;
public FileLogging(final File toWrite) {
this.toWrite = toWrite;
}
@Override
public void write(String message) {
try {
final FileWriter fos = new FileWriter(toWrite);
fos.write(message);
fos.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
Para obtener el código fuente completo, consulte mi repository github.
Ambos son muy similares, y ambos son consumidos por el código del cliente de manera similar. A diferencia de lo que dice la respuesta más popular anterior, ambas permiten la selección del algoritmo en tiempo de ejecución .
La diferencia entre los dos es que mientras el patrón de estrategia permite que diferentes implementaciones utilicen formas completamente diferentes de lograr el resultado deseado, el patrón de método de plantilla especifica un algoritmo general (el método de "plantilla") que se utilizará para lograr el resultado: - la única opción que queda para las implementaciones específicas (subclases) son ciertos detalles de dicho método de plantilla. Esto se hace haciendo que el método de la plantilla realice llamadas a uno o más métodos abstractos que son reemplazados (es decir, implementados) por las subclases, a diferencia del método de la plantilla, que no es abstracto ni reemplazado por las subclases. .
El código del cliente hace una llamada al método de la plantilla usando una referencia / puntero del tipo de clase abstracta apuntando a una instancia de una de las sub clases concretas que se puede determinar en el tiempo de ejecución al igual que cuando se usa el Patrón de estrategia.
Creo que los Diagramas de Clase de ambos patrones muestran las diferencias.
Estrategia
Encapsula un algoritmo dentro de una clase
Enlace a la imagen
Método de plantilla
Aplazar los pasos exactos de un algoritmo a una subclase
Enlace a la imagen
El patrón de Plantilla es similar al patrón de Estrategia. Estos dos patrones difieren en alcance y en metodología.
La estrategia se usa para permitir que las personas que llaman puedan variar un algoritmo completo, por ejemplo, cómo calcular diferentes tipos de impuestos, mientras que el Método de plantilla se usa para variar los pasos en un algoritmo. Debido a esto, la estrategia es de grano más grueso. La plantilla permite controles más detallados en el futuro de las operaciones y, sin embargo, permite que las implementaciones de estos detalles varíen.
La otra diferencia principal es que Strategy usa la delegación mientras que el Método de plantilla usa la herencia. En Estrategia, el algoritmo se delega en la otra clase de xxxStrategy a la que el sujeto tendrá una referencia, pero con la plantilla se subclasifica la base y se anulan los métodos para realizar cambios.
de http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html
El patrón de plantilla se usa cuando una operación en particular tiene algún comportamiento invariante que se puede definir en términos de otros comportamientos primitivos variables. La clase abstracta define el (los) comportamiento (s) invariante (s), mientras que las clases implementadoras definen los métodos dependientes. En una estrategia, las implementaciones de comportamiento son independientes: cada clase implementadora define el comportamiento y no hay código compartido entre ellas. Ambos son patrones de comportamiento y, como tales, se consumen de manera muy similar por los clientes. Normalmente, las estrategias tienen un único método público: el método execute()
, mientras que las plantillas pueden definir un conjunto de métodos públicos, así como un conjunto de primitivas privadas de apoyo que las subclases deben implementar.
Los dos patrones podrían usarse fácilmente juntos. Es posible que tenga un patrón de estrategia donde varias implementaciones pertenecen a una familia de estrategias implementadas utilizando un patrón de plantilla.
En el método de plantilla de este patrón de diseño, uno o más pasos de algoritmo pueden ser reemplazados por subclases para permitir comportamientos diferentes mientras se asegura que el algoritmo general aún se sigue (Wiki).
El nombre de patrón Método de plantilla significa lo que es. Digamos que tenemos un método CalculateSomething () y queremos moldear este método. Este método se declarará en la clase base como un método no virtual. Digamos que el método se ve así.
CalculateSomething(){
int i = 0;
i = Step1(i);
i++;
if (i> 10) i = 5;
i = Step2(i);
return i;
} La implementación del método Step1 y Step2 puede darse por clases derivadas.
En Strategy Pattern no hay implementación proporcionada por la base (Esta es la razón por la cual la base es realmente una interfaz en el diagrama de clases)
El ejemplo clásico es ordenar. En función de la cantidad de objetos que se deben clasificar, se crea la clase de algoritmo adecuada (fusión, burbuja, rápido, etc.) y todo el algoritmo se encapsula en cada clase.
Ahora podemos implementar la clasificación como un método de plantilla? Ciertamente puede, pero no encontrará mucha / ninguna característica común que deba abstraerse y colocarse en la implementación base. Por lo tanto, anula el propósito del patrón de método de la plantilla.
En la estrategia, las subclases de patrones ejecutan el programa y controlan el algoritmo. Aquí el código está duplicado en las subclases. El conocimiento del algoritmo y cómo implementarlo se distribuye en muchas clases.
En patrón de plantilla, la clase base tiene algoritmo. Maximiza la reutilización entre las subclases. Como el algoritmo se encuentra en un lugar, la clase base lo protege.
Herencia versus agregación (is-a versus has-a). Son dos formas de lograr el mismo objetivo.
Esta pregunta muestra algunas de las ventajas y desventajas entre las elecciones: Herencia vs. Agregación
La estrategia se expone como un método de interfaz y plantilla como la clase abstracta. Esto generalmente se usa mucho en frameworks. por ejemplo, la clase MessageSource de Spring framework es una interfaz de estrategia para resolver mensajes. El cliente usa una implementación particular (estrategia) de esta interfaz.
Y la implementación abstracta de la misma interfaz AbstractMessageSource, que tiene una implementación común de la resolución de mensajes y expone el método resuelto solveCode () para que las subclases puedan implementarlos a su manera. AbstractMessageSource es un ejemplo de método de plantilla.
La principal diferencia entre los dos es cuando se elige el algoritmo concreto.
Con el patrón de método de plantilla, esto ocurre en tiempo de compilación subclasificando la plantilla. Cada subclase proporciona un algoritmo concreto diferente implementando los métodos abstractos de la plantilla. Cuando un cliente invoca métodos de la interfaz externa de la plantilla, la plantilla llama a sus métodos abstractos (su interfaz interna) según sea necesario para invocar el algoritmo.
class ConcreteAlgorithm : AbstractTemplate
{
void DoAlgorithm(int datum) {...}
}
class AbstractTemplate
{
void run(int datum) { DoAlgorithm(datum); }
virtual void DoAlgorithm() = 0; // abstract
}
Por el contrario, el patrón de Estrategia permite que un algoritmo sea elegido en tiempo de ejecución por contención . Los algoritmos concretos se implementan por clases o funciones separadas que se pasan a la estrategia como un parámetro para su constructor o un método setter. El algoritmo elegido para este parámetro puede variar dinámicamente según el estado o las entradas del programa.
class ConcreteAlgorithm : IAlgorithm
{
void DoAlgorithm(int datum) {...}
}
class Strategy
{
Strategy(IAlgorithm algo) {...}
void run(int datum) { this->algo.DoAlgorithm(datum); }
}
En resumen:
- Patrón de método de plantilla: selección del algoritmo en tiempo de compilación por subclasificación
- Patrón de estrategia: selección del algoritmo en tiempo de ejecución por contención
No, no necesariamente se consumen de la misma manera. El patrón de "método de plantilla" es una forma de proporcionar "orientación" a futuros implementadores. Les está diciendo: "Todos los objetos Persona deben tener un Número de Seguridad Social" (este es un ejemplo trivial pero logra transmitir la idea correctamente).
El patrón de estrategia permite que múltiples implementaciones posibles sean conectadas y desconectadas. Por lo general, no se implementa a través de la herencia, sino que permite que la persona que llama apruebe la implementación deseada. Un ejemplo podría ser que se le otorgue a un Calculador de envío una de varias formas diferentes de calcular los impuestos (una implementación de NoSalesTax y una implementación de PercentageBasedSalesTax tal vez).
Entonces, a veces, el cliente realmente le dirá al objeto qué estrategia usar. Como en
myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);
Pero el cliente nunca haría eso para un objeto basado en el Método de plantilla. De hecho, es posible que el cliente ni siquiera sepa que un objeto se basa en el Método de plantilla. Esos métodos abstractos en el patrón de Método de plantilla incluso podrían estar protegidos, en cuyo caso el cliente ni siquiera sabría que existen.
Probablemente se refiera a un patrón de método de plantilla. Tienes razón, sirven necesidades muy similares. Yo diría que es mejor usar el método de la plantilla en los casos en que tenga un algoritmo de "plantilla" que tenga pasos definidos donde las subclases anulen estos pasos para cambiar algunos detalles. En el caso de la estrategia, debe crear una interfaz y, en lugar de la herencia, está utilizando la delegación. Yo diría que es un patrón un poco más poderoso y tal vez mejor de acuerdo con los principios de inversión de dependencia DIP. Es más poderoso porque define claramente una nueva abstracción de la estrategia, una forma de hacer algo que no se aplica al método de la plantilla. Entonces, si esta abstracción tiene sentido, úsala. Sin embargo, usar el método de plantilla puede darle diseños más simples en casos simples, lo cual también es importante. Considere qué palabras se ajustan mejor: ¿tiene un algoritmo de plantilla? ¿O es la clave aquí que tienes una abstracción de la estrategia, una nueva forma de hacer algo?
Ejemplo de un método de plantilla:
Application.main()
{
Init();
Run();
Done();
}
Aquí heredas de la aplicación y sustituyes lo que se hará exactamente en init, run y done.
Ejemplo de una estrategia:
array.sort (IComparer<T> comparer)
Aquí, cuando se escribe un comparador, no se hereda de una matriz. Array delega el algoritmo de comparación a un comparador.
Sugeriría que leyeras this artículo. Explica las diferencias en un ejemplo de caso real.
Cita del artículo
" Como se puede ver, implementar clases también depende de la clase de método de la plantilla. Esta dependencia hace que cambie el método de la plantilla si se quieren cambiar algunos de los pasos del algoritmo. Por otro lado, la estrategia encapsula completamente el algoritmo. clases para definir completamente un algoritmo. Por lo tanto, si llega algún cambio, uno necesita cambiar el código para las clases escritas previamente. Esta fue la razón principal por la que elegí la estrategia para diseñar las clases.
Una característica del método de plantilla es que el método de plantilla controla el algoritmo. Lo cual puede ser algo bueno en otra situación, pero en mi problema esto me estaba restringiendo a diseñar las clases. Por otro lado, la estrategia no controla los pasos de un algoritmo que me permite agregar métodos de conversión completamente diferentes. Por lo tanto, en mi caso, la estrategia me ayuda para la implementación.
Una desventaja de la estrategia es que hay demasiada redundancia de código y menos intercambio de código. Como es obvio en el ejemplo presentado de este artículo, tengo que repetir el mismo código en cuatro clases una y otra vez. Por lo tanto, es difícil de mantener porque si se cambia la implementación de nuestro sistema, como el paso 4, que es común a todos, tendré que actualizar esto en las 5 clases. Por otro lado, en el método de la plantilla, solo puedo cambiar la superclase y los cambios se reflejan en las subclases. Por lo tanto, el método de plantilla proporciona una cantidad muy baja de redundancia y una gran cantidad de código compartido entre las clases.
La estrategia también permite cambiar el algoritmo en tiempo de ejecución. En el método de la plantilla uno tendrá que reiniciar el objeto. Esta característica de la estrategia proporciona gran cantidad de flexibilidad. Desde el punto de vista del diseño, uno tiene que preferir la composición a la herencia. Por lo tanto, el uso de un patrón de estrategia también se convirtió en la elección principal para el desarrollo ".
Similitudes
Los patrones de estrategia y método de plantilla tienen muchas similitudes entre ellos. Los patrones de método de Estrategia y Plantilla se pueden usar para satisfacer el Principio de Abierto Cerrado y hacer que el módulo de software sea fácil de extender sin cambiar su código. Ambos patrones representan la separación de la funcionalidad genérica de la implementación detallada de esa funcionalidad. Sin embargo, difieren un poco en términos de granularidad que ofrecen.
Diferencias
Estas son algunas de las diferencias que he observado al estudiar estos dos patrones:
- En Estrategia, el acoplamiento entre el cliente y la estrategia es más flexible, mientras que en el Método de plantilla, los dos módulos están más estrechamente acoplados.
- En Strategy, principalmente se utiliza una interfaz, aunque también se puede usar la clase abstracta dependiendo de la situación, y no se usa la clase concreta, mientras que en el método Template se usa principalmente la clase abstracta o la clase concreta, no se utiliza la interfaz.
- En el patrón de Estrategia, generalmente el comportamiento completo de la clase se representa en términos de una interfaz, por otro lado, el método de Plantilla se usa para reducir la duplicación de código y el código repetitivo se define en el marco base o clase abstracta. En el Método de plantilla, incluso puede haber una clase concreta con implementación predeterminada.
- En palabras simples, puede cambiar toda la estrategia (algoritmo) en el patrón de Estrategia, sin embargo, en el método de Plantilla, solo cambian algunas cosas (partes del algoritmo) y el resto de las cosas permanecen sin cambios. En el Método de plantilla, los pasos invariables se implementan en una clase base abstracta, mientras que los pasos variantes reciben una implementación predeterminada o ninguna implementación. En el método de Plantilla, el diseñador de componentes exige los pasos necesarios de un algoritmo y el orden de los pasos, pero permite que el cliente componente amplíe o reemplace algunos de estos pasos.
La imagen está tomada del blog bitesized .
Método de la plantilla:
- Se basa en la herencia
- Define esqueleto de algoritmo que no puede ser cambiado por sub clases. Solo ciertas operaciones pueden ser anuladas en sub clases
- La clase para padres controla completamente el algoritmo y difiere solo ciertos pasos para clases concretas
- La vinculación se realiza en tiempo de compilación
Estructura de la Template_method :
Estrategia:
- Se basa en la delegación / composición
- Cambia las agallas del objeto modificando el comportamiento del método
- Se usa para cambiar entre familia de algoritmos
- Cambia el comportamiento del objeto en tiempo de ejecución al reemplazar por completo un algoritmo con otro algoritmo en tiempo de ejecución
- La vinculación se realiza en tiempo de ejecución
Estructura de la WikiPedia :
Eche un vistazo al método de la Plantilla y artículos de Strategy para una mejor comprensión.
Artículos Relacionados: