ejemplos - patrones de diseño java
Patrón de polimorfismo vs Estrategia (9)
Estoy confundido de que todo lo que se logra a través de Strategy Pattern es básicamente posible por polimorfismo.
No puede conducir un automóvil sin un volante. Eso no significa que un volante sea un automóvil. De manera similar, el patrón de Estrategia se basa en el polimorfismo, pero eso no significa que sean la misma cosa.
El propósito del patrón de Estrategia es promover el uso de la composición (has-a) sobre la herencia (is-a). En lugar de que su clase herede el comportamiento de una súper clase, usted define el comportamiento en una clase separada y su clase tiene una referencia a ella.
En lo que respecta al ejemplo, eche un vistazo a this respuesta que hace un buen trabajo.
¿Cuál es la diferencia entre el patrón de Strategy
y el Polymorphism
en Java?
Estoy confundido de que todo lo que se logra a través de Strategy Pattern es básicamente posible por polimorfismo. Corrígeme si me equivoco en este sentido.
Por favor, también dame un ejemplo para erradicar mi confusión.
Patrón de polimorfismo vs estrategia con ejemplos de Java centrales
Diferencia básica: el polimorfismo es el concepto de lenguaje de programación, y el patrón de estrategia es uno de los patrones de diseño de comportamiento de GoF .
El polimorfismo es la provisión de una única interfaz para entidades de diferentes tipos.
Ejemplo: El volante (es decir, la interfaz) es el mismo sin importar qué tipo de mecanismo de dirección real se use. Es decir, el volante funciona igual si su auto tiene dirección manual, dirección asistida o dirección de piñón y cremallera. Por lo tanto, una vez que sepa cómo operar el volante, puede conducir cualquier tipo de automóvil.En la programación, el polimorfismo se implementó de dos maneras:
- Polimorfismo de unión temprana / estático / tiempo de compilación (por ejemplo, sobrecarga de función)
- Polimorfismo de unión tardía / dinámico / de tiempo de ejecución (por ej .: anulación de función)
Un patrón de Estrategia define un conjunto de algoritmos que se pueden usar indistintamente.
- El patrón de Estrategia es un patrón dinámico (¿Cómo desea ejecutar un comportamiento en el software?).
Ejemplo de core java:
java.util.Comparator#compare()
, ejecutado entre otrosCollections#sort()
.Los modos de transporte son análogos al patrón de diseño de la estrategia . Usamos auto, bicicleta, autobús, tren local, etc. estrategias diferentes para ir a la oficina día tras día.
P: ¿Cuál es la diferencia entre el patrón de estrategia y el polimorfismo en Java?
Las preguntas son ciertamente confusas ya que inicialmente parece no haber ninguna relación entre estas dos ideas.
El polimorfismo es un concepto mucho más amplio en programación y sí, el patrón de estrategia en Java usa una forma de polimorfismo catalogada como polimorfismo de inclusión para lograr su intención, pero este no es el único tipo de polimorfismo que existe, ni es la única forma de implementar el patrón de estrategia como lo demostraré pronto.
Además, el polimorfismo no es algo que solo existe en Java o en lenguajes de programación orientados a objetos. Diferentes formas de polimorfismo existen en todos los paradigmas de programación y no en todos los idiomas se ve obligado a utilizar el polimorfismo para implementar un patrón de estrategia (por ejemplo, lenguajes funcionales).
Para una discusión adicional sobre este tema, lea esta otra respuesta donde hemos discutido si el polimorfismo es posible sin herencia y proporciono referencias y ejemplos interesantes para otros tipos de polimorfismo como el polimorfismo paramétrico y ad-hoc.
Idealmente, esto les revelará que el polimorfismo es un concepto más amplio que va más allá de los límites de la programación orientada a objetos e incluso más allá de la herencia y la subtipificación.
P: Estoy confundido de que todo lo que se logra a través de Strategy Pattern es básicamente posible por polimorfismo. Corrígeme si me equivoco en este sentido.
Entonces, para mí, la única relación entre estos dos conceptos es que, primero, el patrón de estrategia aprovecha el poder del polimorfismo disponible en lenguajes como Java para implementar su intención, y segundo, que el polimorfismo puede considerarse en sí mismo un patrón.
Por ejemplo, considere esta cita del libro de GoF:
Si asumimos los lenguajes de procedimiento, podríamos haber incluido patrones de diseño llamados ''herencia'', ''encapsulación'' y ''polimorfismo''.
Es solo que rara vez pensamos en el polimorfismo como un patrón, primero porque implica muchas cosas y porque se implementa de manera diferente en diferentes idiomas y también porque se presenta como una característica del lenguaje.
En su libro Elemental Design Patterns, Jason Mc C. Smith comenta sobre la cita anterior de GoF:
El patrón son conceptos independientes del lenguaje; toman forma y se convierten en soluciones concretas cuando los implementa dentro de un lenguaje particular con un conjunto dado de características de lenguaje y construcciones [...] Esto significa que es un poco extraño hablar de "patrón de diseño de Java", "patrones de diseño de C ++". "," Patrón de diseño de la esfera web ", etc., aunque todos lo hacemos. Es una forma de taquigrafía levemente perezosa para lo que realmente queremos decir, o debería yo: diseñar patrones implementados en Java, C ++, WebSphere, etc., independientemente del idioma o la API.
Entonces, como puede ver, está pensando en el patrón de Estrategia desde la perspectiva de la implementación de Java, pero en otros paradigmas de lenguaje dicho patrón puede haberse implementado de diferentes maneras, probablemente sin usar herencia en absoluto, por ejemplo, en funcional puro. los lenguajes de programación esto se implementa sin duda usando funciones de alto orden y composición de funciones .
Como tal, esto sería una implementación de patrón de estrategia sin recurrir al polimorfismo de inclusión en absoluto. En una estrategia de composición de funciones todavía podemos estar usando otras formas de polimorfismo (por ejemplo paramétrico), pero eso no es un requisito para el patrón de estrategia
P: Por favor, también dame un ejemplo para erradicar mi confusión.
Como se discutió anteriormente, en Java probablemente nos veamos obligados a usar un polimorfismo de inclusión para implementar un patrón de Estrategia, pero como se explicó anteriormente, los patrones no son algo que pertenece a un lenguaje específico, por lo que si pensamos en el patrón de estrategia como un concepto fuera de los límites de idioma, verá fácilmente otros idiomas implementar esto de diferentes maneras.
En algún lenguaje funcional hipotético, puedo tener una función que lea algunos datos de un archivo, tal vez el archivo esté encriptado y usted necesite proporcionar una estrategia de descifrado:
function readFile(path: String, decrypt: string -> string) {
return decrypt(loadFromDisk(path));
}
Y ese argumento de decrypt
es una función que sirve al propósito de un patrón de estrategia, encapsula un algoritmo intercambiable.
Ahora puedes hacer
readFile("customers.txt", aes)
readFile("finance.txt", blowfish)
Donde aes
y blowfish
son estrategias de desencriptación de funciones.
Hay docenas de idiomas que funcionan así, SML, Haskell, JavaScript, etc.
Ante todo. El polimorfismo puede significar dos cosas diferentes. Más comúnmente, el polimorfismo se refiere a un tipo polimórfico. Sin embargo, estás pidiendo el patrón.
El código polimórfico puede cambiar cada vez que se ejecuta mientras la función del código permanece igual. Un ejemplo fácil es hacer 1 + 3 = 4 en vez de 5-1 = 4. Ambos logran el mismo resultado usando código diferente. Esto es útil para código que no quiere ser reconocido, es decir, virus informáticos o código criptográfico.
El patrón de estrategia, por otro lado, usa una familia de algoritmos que pueden intercambiarse. Esto podría usarse al traducir texto. Primero, algún código determina el idioma. si el idioma es sueco o español, el texto será procesado por diferentes funciones de la misma familia, translateSwedish () o translateSpanish ().
Para redondear las cosas. El código polimórfico usa un código diferente que logra el mismo resultado. Mientras que Strategy usa códigos diferentes para lograr mejores resultados.
Considera esto
tenemos animales y un objeto de patrón de estrategia para describir cómo se mueven ... por ejemplo
volar / nadar / caminar
Dado el gran número de animales que usan cualquiera de estos métodos (es decir, miles de animales diferentes vuelan), necesitamos usar el mismo código para muchos animales diferentes. Ese código solo debería existir en un lugar, de modo que se pueda cambiar fácilmente y no ocupe ningún espacio innecesario.
En este ejemplo, un enfoque de polimorfismo directo dará como resultado una duplicación masiva del código. Un enfoque más complejo que coloca una clase intermedia entre animal y decir petirrojo no toma en consideración que la forma en que se mueve un animal no es realmente lo que lo define. Además, es posible que un animal tenga otros objetos estratégicos y no todos pueden ser polimórficos a través de clases intermedias.
Para mí, el enlace de la de y el ejemplo en Wikipedia son lo suficientemente claros, pero trataré de darle un nuevo ejemplo. Como decían, Strategy Pattern es principalmente una forma de cambiar el comportamiento de un algoritmo en tiempo de ejecución . Por supuesto, puede lograrlo de muchas formas diferentes (como mantener un valor y usar un conmutador, pero no sería tan bueno como el Patrón de estrategia).
Digamos que estás desarrollando un juego de estrategia por turnos con dos tipos de Unidades : Infantería y Tanque (subclases de Unidad). Su terreno podría ser llanuras , ferrocarril o bosques .
class Unit{
MovementStrategy ms;
final int baseMovement;
int x,y;
public Unit(int baseMovement){
this.baseMovement = baseMovement;
}
abstract void fire();
void moveForward(){
x = x + ms.getHexagonsToMove(baseMovement);
}
void setMovementStrategy(MovementStrategy ms){
this.ms = ms;
}
}
Cualquier subclase de Unidad debe implementar el método de fuego () porque va a ser completamente diferente para ellos (disparos de tanques pesados de larga distancia e infantería dispararon varias balas de luz de corta distancia). En este ejemplo usamos polimorfismo / herencia normal ya que el método fire () será muy diferente para cualquier unidad, y no cambiará durante el juego .
class Infantry extends Unit{
public Infantry(){
super(2);
}
void fire(){
//whatever
}
}
class Tank extends Unit{
public Tank(){
super(5);
}
void fire(){
//whatever
}
}
Las unidades también pueden moverse, y tienen un movimiento de base de campo que mantiene el número de hexágonos que pueden caminar. Estamos desarrollando un juego de estrategia, no una simulación del mundo real, por lo que no nos importa cómo se muevan, solo queremos agregar un valor a sus coordenadas (en mi ejemplo, solo uso la coordenada X para obtener un código más simple) ) Si todo el terreno fuera el mismo, no necesitaríamos ningún objeto de Estrategia ... ¡pero tenemos que cambiar el comportamiento del método move () en el tiempo de ejecución!
Por lo tanto, implementamos una clase MovementStrategy diferente para cada uno de nuestros tipos de Terrain, y programamos nuestro juego para desencadenar una setMovementStrategy () a cualquier unidad que se mueva en cada hexágono. Y ni siquiera necesitamos escribir nada más en nuestras subclases de Unidad.
interface MovementStrategy{
public int getHexagonsToMove(int base);
}
class PlainMovementStrategy implements MovementStrategy{
public int getHexagonsToMove(int base){
return base;
}
}
class RailroadMovementStrategy implements MovementStrategy{
public int getHexagonsToMove(int base){
return base*3;
}
}
class ForestMovementStrategy implements MovementStrategy{
public int getHexagonsToMove(int base){
return (int)(base/2);
}
}
Ahora, cuando cualquier unidad se mueve dentro de un bosque , llamamos
unit.setMovementStrategy(new ForestMovementStrategy());
Y tan pronto como va a una Llanura , lo hacemos:
unit.setMovementStrategy(new PlainMovementStrategy());
Ahora podemos cambiar la distancia a la que nuestras unidades se mueven según el Terreno, y no es necesario volver a escribir en ninguna de las subclases.
Espero que esto te ayude a comprender mejor la diferencia.
Si está estableciendo una analogía donde:
- en un caso tiene varios métodos invalidables;
- en el otro caso, tienes una interfaz de Estrategia con varias implementaciones,
entonces la diferencia es el grado de acoplamiento, que es muy fuerte en el primer caso, mientras que en el segundo caso cualquier código extraño puede participar en la lógica de su clase al contribuir con su implementación de la Estrategia.
Una definición para Polimorfismo es la provisión de una única interfaz para entidades de diferentes tipos.
Con eso en mente, digamos que tiene una interfaz de "pájaro" y todas sus clases de aves deben implementar el método "laysEggs ()", bueno, no hay problema que funcione. Y a medida que sigues codificando tu "programa paraísos para pájaros" ahora agregas el "fly ()" y te das cuenta de que la sobrecarga y anulación de pingüinos y kiwi es innecesaria ya que en la vida real no pueden volar, pero aún debes implementar ese método. Esto puede volverse tedioso e inútil ya que te enfrentas a avestruces y otros que no pueden volar. Y lo peor de todo al agregar el método "nadar ()" porque incluso menos aves pueden nadar. Como ya sabrá, el patrón de estrategia resuelve este problema.
En términos de hombre cojo, puede pensar en el polimorfismo como un conglomerado de prácticas, mientras que el patrón de estrategia es la mejor práctica para un caso específico. Ejemplo: el patrón de estrategia se debe usar cuando el comportamiento de un algoritmo debe seleccionarse en tiempo de ejecución (a través de algoritmos intercambiables). Y aunque es cierto que todo lo que se logra mediante Patrón de estrategia es básicamente posible por polimorfismo, sin conocimiento del Patrón de estrategia esto te dejaría con el problema de "reinventar la rueda" para resolver este problema específico. En conclusión, son muy diferentes, incluso si uno se basa en el otro. Lo dejo para ver el código de "Ender Muab''Dib", ya que está bien explicado si todavía quiere un ejemplo de código de mi parte solo pregunte, aplausos y espero haber ayudado.
El polimorfismo es un principio y la estrategia es un patrón de diseño
De la page documentación de page
La definición del diccionario de polimorfismo se refiere a un principio en biología en el cual un organismo o especie puede tener muchas formas o etapas diferentes. Este principio también se puede aplicar a la programación orientada a objetos y lenguajes como el lenguaje Java. Las subclases de una clase pueden definir sus propios comportamientos únicos y aún compartir algunas de las mismas funcionalidades de la clase principal.
El polimorfismo se puede lograr en tiempo de compilación (sobrecarga de método) y tiempo de ejecución (anulación de método).
- Define una familia de algoritmos,
- Encapsula cada algoritmo, y
- Hace que los algoritmos sean intercambiables dentro de esa familia.
La estrategia puede usar el principio de polimorfismo en tiempo de ejecución para lograr la funcionalidad deseada.
El patrón de estrategia tenía un componente más llamado Contexto en su diagrama de URL. Consulte las siguientes publicaciones SE:
Ejemplo del mundo real del patrón de estrategia
¿Este patrón de estrategia Java tiene una clase de contexto redundante?
Pocos artículos más útiles:
estrategia por fuente