Principio abierto cerrado (OCP) Parte II

Teniendo en cuenta los comentarios recibidos en la entrada anterior y en forma personal, paso a comentar otra forma de poder cumplir con este principio abierto y cerrado (OCP): la implementación del patrón de diseño strategy.
Este patrón de diseño, establece que los comportamientos no deben heredarse. En su lugar, se deben encapsular usando interfaces.
Para dar un ejemplo, me remitiré a uno ya existente en el libro Head first design patterns.
Debemos programar una simulación de un pato, para ello, creamos una clase abstracta denominada Pato, la cual posee los métodos (o comportamientos) Cuac(), Nadar() y Mostrar(). Todos los patos hacen cuac y nadan, por lo que esta clase implementa dichos métodos. Pero, como todos los patos lucen diferentes, el método Mostrar será abstracto, es decir, se implementará en cada subclase.

En un segundo análisis, notamos el hecho de que nos ha faltado un comportamiento: Volar. Por este motivo, incluimos e implementamos el método con el mismo nombre en nuestra clase abstracta Pato. De esta manera, las subclases de Pato ya pueden volar.
Pues bien, qué pasa si agregamos una nueva clase de pato, el pato de goma. Tendría, equivocadamente, la posibilidad de volar. Si resolviéramos esto a través de la herencia, sólo tendríamos que sobrescribir el método Volar y listo, todo arreglado. Pero no, porque si además agregáramos otra clase, por ejemplo, el pato señuelo, además de no ser capaz de volar, tampoco tiene la capacidad de hacer cuac.
Es evidente que la herencia no resuelve este problema. Que tal si implementamos interfaces. Extraemos el método Volar y Cuac fuera de la clase Pato y creamos dos interfaces para ellos. De esta manera, sólo implementarían la clase que corresponda para aquellos patos que pueden volar o hacer cuac.

En primera instancia, parece una buena idea, salvo que tiene una pequeña contra: el código repetido. Tanto el pato real como pato pelirrojo, hacen cuac y vuelan del mismo modo. Si nos pareció mal pisar métodos heredados para remover comportamientos, duplicar código es casi tan malo como eso. Sobre todo, si en lugar de tener sólo dos subclases que los implementan, tuviéramos 48 y hubiera que modificar todos solamente para introducir un cambio.
Como la única constante en software, es el cambio, nos conviene aplicar los patrones de diseño. Para ello, separemos aquellos aspectos de nuestro código que varían de los que permanecen iguales.
Para este caso, lo que varía entre las distintas clases de patos, son los comportamientos de volar y hacer cuac. Claramente podemos notar en el caso de volar dos implementaciones diferentes: volar y no volar. Mientras que en el caso del sonido, tenemos tres: el cuac propiamente dicho, el chillido y sin sonido.
Con este diseño, los comportamientos extraídos ahora pueden ser reutilizados por otras clases ya que no están limitados solamente a las clases a las que pertenecían.
Teniendo en cuenta la creación de estos comportamientos, sólo nos resta modificar la clase Pato para que implemente estos cambios.
Las implementaciones de PatoReal, PatoPelirrojo, PatoDeGoma y PatoSeñuelo instanciarán las clases de comportamiento según corresponda.

0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere