Sie sind auf Seite 1von 92

Patrones de

Diseo
Introduccin
Introduccin Alguien ha
resuelto tus problemas
El por qu y el cmo puedes explotar las sabidura
y lecciones aprendidas por otros desarrolladores
que han pasado por los mismos problemas de
diseo y han sobrevivido
Beneficios de los patrones de diseo
Veremos algunos principios OO clave
La mejor manera de usar patrones es cargarlos
en tu mente y reconocer lugares en tu diseo y en
aplicaciones existentes donde poder aplicarlos
No se reutiliza cdigo, se reutiliza experiencia
Todo empieza con un simple
juego
Joe trabaja para una
compaa que se dedica a
crear juegos de simulacin
de estanques de pato
El juego muestra una gran
variedad de especies,
nadando y haciendo
graznidos
El diseador inicial del
sistema utiliz tcnicas
estndares OO y cre una
superclase Pato de la cual
las subclases de Pato
heredan
Todo empieza con un simple
juego
Caso
En el ltimo ao, la compaa ha tenido
bastante presin debido a sus competidores
Despus de una lluvia de ideas, los ejecutivos
de la compaa piensan que es hora de
innovar
Ellos necesita algo realmente sorprendente
para mostrar en la reunin de inversionistas la
prxima semana
Ahora necesitamos que los
patos VUELEN
Los ejecutivos decidieron que patos volando
es justamente lo que esta aplicacin necesita
para vencer a sus competidores
Y por supuesto, la jefa de Joe les dijo que no
era problema para Joe, y que terminara en
una semana
Despus de todo dijo la jefa Joe es un
programador OO Qu tan difcil puede
ser?
Ahora necesitamos que los
patos VUELEN
Solo necesito aadir un
nuevo mtodo llamado Volar
a Pato y los dems
heredarn automticamente.
Ahora necesitamos que los
patos VUELEN
Pero algo sali terriblemente
mal
Joe, estoy en la reunin de
inversionistas, estamos
revisando el juego, y hay
Patos de Goma volando por
todos lados. Es una broma o
que?
Qu pas?
Joe nunca not que no todas las subclases de
pato deben Volar
Cuando Joe agreg nuevo comportamiento a la
superclase, tambin estaba agregando
comportamiento no apropiado a las subclases
Ahora tiene objetos inertes volando en el juego
Una actualizacin localizada al cdigo caus
un efecto secundario no local (patos de goma
voladores)
Qu pas?
Patos de goma no
graznan, el
comportamiento es
sobrescrito a Chillar
Qu pas?
Lo que l pens que
era un buen uso de
herencia con el
propsito de
reutilizacin no
result tan bueno
cuando lidiamos con
mantenimiento
OK, hay una pequea
falla en mi diseo. No
se por qu no le
pueden llamar una
nueva funcin. Es
simptico
Joe piensa en herencia
PatoGoma
Mostrar(){
//Muestra un pato de goma
}
Graznar(){
//Sobrescribir a Chillar
}
Volar(){
//No hacer nada
}
Joe piensa en herencia
Pero que pasara si
aumentamos patos
seuelo de madera en
el futuro. Ellos no
vuelan ni graznan
Ejercicio
A. El cdigo se duplica en las subclases
B. Cambios en tiempo de ejecucin son difciles
C. No podemos hacer que los patos bailen
D. Se complica obtener conocimiento del comportamiento de
todos los patos
E. Los patos no pueden volar y graznar al mismo tiempo
F. Los cambios en el cdigo podran afectar a otros patos sin
intencin
De las siguientes opciones elija cules serian las desventajas de
utilizar herencia en el ejemplo anterior
Y si usamos una Interfaz?
Joe se dio cuenta de que la herencia probablemente no
era la respuesta
Recibi un memo de los ejecutivos diciendo que
quieren actualizar el producto cada seis meses (de
maneras que ellos an no han decidido)
Joe sabe que las especificaciones seguirn cambiando
y ser forzado a revisar y probablemente actualizar
Volar() y Graznar() por cada subclase de Pato que se
vaya a crear para siempre!
l necesita una manera ms limpia de hacer que
solamente algunos ( no todos) los tipos de patos vuelen
y graznen
Y si usamos una Interfaz?
Podra sacar el mtodo Volar()
de la superclase Pato y hacerla
una interfaz de esa manera
nicamente los patos que
quieran volar implementan la
interfaz y de paso hago otra
interfaz para Graznar ya que
no todos los patos graznan
Que opinas de este diseo?
Este es un pato de madera

Es la idea ms tonta que se te


ha ocurrido. Si creas que
sobrescribir unos cuantos
mtodos era un error, cmo te
sentirs cuando tengas que
cambiar el comportamiento de
vuelo de las 48 subclases de
pato?
Qu haras t si fueras Joe?
Sabemos que no todas las subclases deben tener
comportamiento de vuelo y graznido
Implementar herencia no es la respuesta correcta
Implementar las interfaces en las subclases resuelve
parte del problema (patos de goma no vuelan)
Sin embargo destruye la reutilizacin del cdigo para
esos comportamientos creando otro tipo de diferente
de pesadilla de mantenimiento
Por supuesto puede haber ms de un tipo de vuelo
incluso entre patos que si vuelan
Qu haras t si fueras Joe?
A estas alturas debemos estar esperando en
un patrn de diseo que llegue cabalgando en
un caballo blanco a salvar el da.
No
Vamos a solucionar las cosas a la antigua,
aplicando buenos principios de diseo OO
Cul es la nica cosa con la que
puedes contar en el desarrollo
de software?
El Cambio
La constante en desarrollo de
software
No importa dnde trabajes
No importa qu construyes
No importa qu lenguaje utilices
No importa qu tan bien diseada este una
aplicacin
Con el tiempo una aplicacin debe crecer y
cambiar o sino morir
Ejercicio
Listar razones para cambiar
cdigo en tus aplicaciones.
Enfocarse en el problema
Usar herencia no funcion muy bien, ya que el
comportamiento de pato sigue cambiando en
todas sus subclases
No es apropiado que todas las subclases
tengan esos comportamientos
Interfaces sonaba prometedor al principio
solo patos que deban volar Volaran- pero
como en las interfaces no se implementa
cdigo, no existe la reutilizacin de cdigo
Enfocarse en el problema
Es decir, cuando se necesite cambiar el
comportamiento, estamos forzados a rastrear
y cambiarlo en todas las diferentes subclases
donde se hayan definido (probablemente
introduciendo nuevos errores en el camino!)
Por suerte, hay un principio de diseo
justamente para estas situaciones
Principio de diseo
Identifica los aspectos de tu
aplicacin que varan y
sepralos de aquellos que
permanecen igual
Es decir
Toma lo que vara y encapslalo para que no
afecte al resto de tu cdigo.
Hay menos consecuencias de cambio de
cdigo
Hay ms flexibilidad en tus sistemas
En otras palabras
Detectamos algn aspecto de tu cdigo que est
cambiando, por ejemplo con cada nuevo
requerimiento
Sabrs que tienes que sacar los comportamientos
y separarlos del resto que no cambia
Toma las partes que varan y encapslalas,
para que luego puedas alterarlas o extenderlas
sin afectar a las que no lo varan
En otras palabras
El concepto es fcil, pero an as forma la
base para casi todos los patrones
Todos los patrones de diseo proveen una
manera de dejar que algunas partes de un
sistema varen independientemente de
otras partes
Anlisis
Dnde empezamos?...
Segn lo visto, aparte de los comportamientos
volar y graznar, la clase Pato funciona bien y
parece que no hay otras partes de ella que
varen o cambien frecuentemente
Dejaremos, entonces, la clase Pato en paz
Anlisis
Ahora, para separar las partes que cambian de
aquellas que no, vamos a crear dos conjuntos
de clases (separadas totalmente de Pato)
Una para Volar y otra para Graznar
Cada conjunto de clases representar todas las
implementaciones de su comportamiento
respectivo
Por ejemplo, una clase implementa graznar, otra
implementa chillar y otra implementa silencio
Separando lo que cambia de lo
que se queda igual
Sabemos que Volar() y Graznar() son las
partes de la clase Pato que varan entre los
patos
Para separar estos comportamientos de la
clase Pato, sacaremos ambos mtodos de
la clase Pato y crearemos nuevas clases
para representar cada comportamiento
Separando lo que cambia de lo
que se queda igual
Varias implementaciones
de comportamientos
vivirn aqu
Diseando los comportamientos
de Pato
Cmo vamos a disear un conjunto de clases
que implementen los comportamientos de volar y
graznar?
Mantener las cosas flexibles, despus de todo, fue
la inflexibilidad en los comportamientos la que nos
meti en problemas
Sabemos que debemos asignar comportamientos
a las instancias de Pato
Por ejemplo, tal vez queramos instanciar un nuevo
pato de goma, e inicializarlo con un tipo de
comportamiento especfico
Diseando los comportamientos
de Pato
Y ya que estamos por all, por que no
asegurarnos que podemos cambiar el
comportamiento dinmicamente
Debemos incluir mtodos de asignacin
(setter) o propiedades en la clase Pato para
que podamos cambiar los comportamientos
de las subclases en tiempo de ejecucin
Dadas estas metas, veamos el segundo
principio de diseo
Principio de diseo
Programa a una interfaz no
una implementacin
Diseo
Utilizaremos una interfaz para representar
cada comportamiento, por ejemplo Vuelo y
Graznido
Cada implementacin de un comportamiento
va a implementar una de estas interfaces
Diseo
De ahora en adelante, los comportamientos
de Pato vivirn en una clase separada, una
clase que implementa una interfaz de
comportamiento particular
De esta manera, las clases de patos no
necesitarn conocer ningn detalle de las
implementaciones de sus propios
comportamientos
Diseo
As que esta vez no sern los Patos que
implementen las interfaces de Vuelo y Graznido
En lugar de eso, construiremos un conjunto de
clases cuya nica razn de existencia es
representar comportamientos (Ej. Clase Chillar)
Son estas clases de tipo comportamiento, en lugar
de Pato, las que implementarn la interfaz
comportamiento
Diseo
Es decir, contrastando la forma en que
hacamos las cosas antes donde un
comportamiento venia o de una
implementacin de la superclase o de una
implementacin especial en la subclase
En ambos casos dependamos de una
implementacin especfica y no haba
espacio para cambiar el comportamiento (sin
escribir ms cdigo)
Diseo de comportamientos de
Pato
Con nuestro diseo, las
subclases de Pato utilizaran
un comportamiento
representado por una
interfaz (IVuelo, IGraznido)
La implementacin real del
comportamiento (la que
codificaremos en las clases
que implementen las
interfaces) no estar
escondida en las subclases
de Pato
Confusin?
No veo por qu tenemos que
utilizar una interfaz para el
comportamiento de Vuelo.
Podemos hacer exactamente lo
mismo con una superclase
abstracta. No era el objetivo
utilizar polimorfismo?
Programar a una interfaz
significa programar a un sper
tipo
La palabra interfaz est sobrecargada aqu
Existe el concepto de interface, y existe el
constructo interface
Puedes programar a una interfaz, sin
necesidad de usar el constructo interfaz
El objetivo es explotar el polimorfismo
programando a un supertipo
Programar a una interfaz
significa programar a un sper
tipo
Podemos volver a escribir el principio
Programar a un Supertipo ya sea una clase
abstracta o una interfaz, , lo que significa que
la clase que lo declara no necesita saber el
tipo de objeto real
Tal vez ya sepas esto, pero para estar seguros
de que todos estamos en hablando de lo
mismo
Simple ejemplo - Polimorfismo
Imagina una clase
abstracta Animal, con
dos implementaciones
concretas, Perro y
Gato
Simple ejemplo - Polimorfismo
Programar a una implementacin sera:
Perro p = new Perro();
p.Ladrar();
Declarar la variable p como tipo Perro (una
implementacin concreta de Animal) nos hace
codificar a una implementacin concreta a la fuerza
Simple ejemplo - Polimorfismo
Pero Programar a una interfaz/supertipo sera:
Animal animal = new Perro();
Animal.HacerUnSonido();
Sabemos que es un perro, pero podemos utilizar la
referencia animal Polimrficamente
Simple ejemplo - Polimorfismo
Mejor an, en lugar de escribir a la fuerza la
instanciacin del subtipo (new Perro()), asigna la
implementacin concreta en tiempo de ejecucin
Animal animal = Obtener Animal();
animal.HacerUnSonido();
No sabemos Qu animal sea todo lo que nos
importa es que sepa hacer un sonido
Implementar los
comportamientos
Reutilizacin
Con este diseo, otros objetos pueden reutilizar
Volar y Graznar ya que estos mtodos no estn
escondidos dentro de la clase Pato
Podemos aumentar nuevos comportamientos sin
modificar ninguna clase ya existente o tocar
ninguna clase que utiliza los comportamientos
Es decir que obtenemos los beneficios de
REUTILIZACIN sin la carga que viene con la
herencia
Preguntas
Debo implementar mi aplicacin primero y
luego hacer el anlisis y descomponer?
Debemos hacer Pato una interfaz tambin?
No se supone que las clases deben
representar cosas? y deben tener estados y
comportamientos?
Ejercicio
Usando el diseo anterior, qu tenemos que
hacer si necesitamos volar con propulsor?
Una clase que podra utilizar el
comportamiento graznar?
Integrando el comportamiento
de Pato
La clave es que Pato ahora
delegar sus comportamientos en
lugar de usar mtodos definidos en
la misma clase ( o subclase)
Integrando el comportamiento
de Pato - Primero
Aumentamos dos variables a la clase
Pato llamadas IVuelo e IGraznido (
como interfaces, no
implementaciones)
Cada objeto pato le dar valor a estas
variables polimrficamente para
referenciar el comportamiento
especifico que desee en tiempo de
ejecucin(volar con alas, chillar, etc)
Quitamos los mtodos volar y
graznarde la clase Pato (y cualquier
subclase)
Los reemplazamos con dos mtodos
similares llamados IniciarGraznido e
IniciarVuelo()
Integrando el comportamiento
de Pato - Segundo
Implementamos los
mtodos
Para graznar, un Pato
solo le permite al objeto
referenciado en la
variable que haga la
operacin
No importa que tipo de
objeto sea, nicamente
nos interesa que sepa
graznar
Integrando el comportamiento
de Pato - Tercero
Darle valor a las variables
en las clases concretas
Cuando un
PatoGargantilla es
instanciado, su
constructor inicializa las
variables de
comportamiento
declaradas en la clase
padre
Y lo mismo es cierto para
los comportamientos de
vuelo
Atencin
Un momento, no habamos dicho que
no debemos programar a una
implementacin? Y qu estamos
haciendo en ese constructor?
Estamos haciendo una nueva
referencia a una implementacin
concreta de Pato
Programar a una
implementacin
Por ahora estamos programando a una
implementacin
Despus tendremos ms patrones que nos
ayudaran a arreglar esto
Igualmente, debemos notar que mientras
ESTAMOS configurando los comportamientos
a clases concretas, podramos fcilmente
cambiar esto en tiempo de ejecucin
Programar a una
implementacin
Aun tenemos flexibilidad, solo que no estamos
haciendo un buen trabajo inicializando las
variables de manera flexible
Pensemos un momento en cmo podemos
implementar un pato para que su
comportamiento pueda cambiar en tiempo de
ejecucin
Ejercicios
Crear y compilar la clase Pato y una clase que
herede de ella (Pato Gargantilla por ejemplo)
Crear y compilar las interfaces de comportamiento
y dos implementaciones para vuelo y tres para
graznido
Crear una clase de prueba donde se compruebe el
cdigo.
Darle un valor de forma dinmica a una prueba
(vuelo o graznido)
Idea principal en el
comportamiento encapsulado
Debemos tomar una vista area nuevamente al
diseo
Tenemos Patos extendiendo de Pato,
comportamientos de vuelo y graznido
implementados en sus interfaces
Notamos que estamos empezando a describir las
cosas un poco diferente
No pensamos en conjunto de comportamientos
sino en familia de algoritmos
Idea principal en el
comportamiento encapsulado
Los algoritmos representan cosas que hara
un pato n el simulador (diferentes maneras de
Volar), pero podemos fcilmente utilizar esta
tcnica en otros casos (clculo de impuestos)
Presta mucha atencin a las relaciones entre
las clases
De hecho, coge un lpiz y escribe las
relaciones apropiadas (ES UN, TIENE UN,
IMPLEMENTA) en un diagrama
Comportamiento encapsulado
Tiene-un puede ser mejor que
Es-un
La relacin TIENE UN es muy interesante, cada pato
tiene un comportamiento de vuelo y graznido al cual se
le delegan las operaciones volar y graznar
Cuando unimos clases de esta manera estamos
usando composicin
Los Patos son compuestos con el comportamiento
correcto, en lugar de heredarlo
sta es una tcnica importante, y de hecho, ya estamos
usando nuestro tercer principio de diseno:
Principio de diseo
Preferir la composicin sobre la
herencia
Composicin
Como hemos visto, crear sistemas utilizando
composicin nos da mucha ms flexibilidad
No solo. permite encapsular familia de algoritmos
en clases sino que te permite cambiar
comportamientos en tiempo real mientras los
objetos que son compuestos implementen la
interfaz correcta
Composicin se utiliza en muchos patrones de
diseo y veremos algunas ventajas y desventajas
Ejercicio
Reclamo es un dispositivo que los cazadores
utilizan para imitar el llamado de los patos
(graznido). Cmo implementaramos un
reclamo que NO herede de la clase Pato?
Hablando de patrones de diseo
Patrn
ESTRATEGIA
Gracias a este
patrn el simulador
esta listo para
cualquier cambio
Felicitacione
s en tu
primer patrn
El patrn Estrategia
El patrn estrategia define una
familia de algoritmos, encapsula
cada uno de ellos, y los hace
intercambiables. Estrategia deja que
los algoritmos varen
independientemente de los clientes
que lo usan
Rompecabezas
En el siguiente ejemplo
encontraremos clases e
interfaces desordenadas
pertenecientes a un juego de
aventuras, clases de personajes
y comportamiento de armas que
cada personaje puede usar en
el juego. Cada personaje puede
hacer uso de un arma a la vez,
pero puede hacer el cambio de
armas en cualquier momento
durante el juego. Tu debes
arreglar todo
Ordenar las clases
Identificar una clase
abstracta, una interfaz y ocho
clases
Dibujar flechas entre las
clases
Herencia
Interfaz
Tiene un
Colocar el mtodo setArma()
(o el Set de la propiedad
Arma) en la clase correcta
Rompecabezas
Vocabulario compartido
Los patrones de diseo te dan un vocabulario
compartido con otros desarrolladores
Comunicacin ms simple entre
desarrolladores e inspira a otras personas a
aprenderlos
Eleva tu arquitectura pensando a nivel de
patrones en lugar de objetos
Conversacin en local de
comida rpida
Necesito una porcin de queso crema y
mermelada en pan blanco, un helado de
vainilla con decorado de chocolate, un
sndwich de queso a la parrilla con
tocino, una ensalada de atn con pan
tostado, un helado banana Split con dos
bananas y un caf con crema y dos
cucharadas de azcar, oh y tambin
coloca una hamburguesa en la parrilla!
Alice
Conversacin en local de
comida rpida
Dame un QJ. En Blanco, y
Blanco y negro, un Jack
Benny, una radio, y un bote de
casa, un caf regular y una
parrilla
Flo
Conversacin en local de
comida rpida
Cul es la diferencia entre las dos
conversaciones?
Nada!
Son exactamente la misma orden, excepto
que Alice est utilizando el doble de palabras
y tentando la paciencia de el cocinero
Qu tiene Flo que Alice no
tenga?
Un vocabulario compartido con el cocinero
No solo es ms fcil la comunicacin con el
cocinero, sino que le hace recordar menos
cosas pues l tiene todos los patrones del
restaurant en su cabeza
Vocabulario compartido
Los patrones de diseo nos dan un vocabulario
compartido con otros desarrolladores
Una vez que tengamos el vocabulario podemos
comunicarnos ms fcilmente con otros
desarrolladores e inspirar a otros que no los
conocen a aprenderlos
Eleva nuestro pensamiento arquitectnico
dejndonos pensar al nivel de patrn, y no a
nivel de objeto
Conversacin de cubculo
Acabo de crear una clase Broadcast.
Mantiene el rastro de todos los objetos
escuchndolos y en cualquier momento que
os datos lleguen les manda un mensaje a
todos los que lo escuchan. Lo mejor de todo
es que se pueden registrar en cualquier
momento ellos mismos es muy dinmico
Por que no dices
nicamente que
ests utilizando el
patrn
Observador?
Ejercicio
Puedes pensar en vocabularios que sean
usados en otros lugares?
Que cualidades son comunicadas?
Que cualidades se comunican junto a los
nombres de los patrones?
Que cualidades se comunican cuando
decimos patrn estrategia?
El poder de un vocabulario
compartido
Cuando te comunicas con otro desarrollador o
con tu equipo con patrones, tambin comunicas
cualidades, caractersticas y restricciones que
representa ese patrn
Permiten decir ms, con menos
Cuando usas un patrn en una descripcin,
otros desarrolladores reconocen rpidamente el
diseo que tienes en mente
Te permite estar en el diseo
por ms tiempo
Hablar acerca de sistemas de software usando
patrones, te permite mantener la discusin al
nivel de diseo, sin tener que bajar a nivel de
objeto innecesariamente
Puede acelerar tu equipo de
desarrollo
Un equipo bien entrenado en patrones puede
moverse ms rpidamente con menos espacio
para malentendidos
Inspira a desarrolladores junior
a ponerse al da
Desarrolladores junior admiran a los
desarrolladores experimentados. Cuando los
desarrolladores snior utilizan patrones de
diseo, los junior se motivan a aprenderlos.
Cmo puedo usar los patrones
de diseo?
Todos usamos frameworks como .Net o Java
API
Los tomamos y escribimos cdigo a su API,
compilamos y creamos programas
aprovechando el cdigo de alguien ms
Librerias y Frameworks van junto al modelo de
desarrollo donde podemos escoger y usar
componentes y enchufarlos directamente
Cmo puedo usar los patrones
de diseo?
Pero nos ayudan a estructurar nuestras
aplicaciones para que sean ms fciles de
entender, mantener y al mismo tiempo
flexibles
Patrones de diseo no van directamente en el
cdigo, sino en tu cabeza, y una vez
familiarizado con ellos podremos aplicarlos en
nuestros nuevos o antiguos diseos
Preguntas
Si son tan grandiosos, por qu nadie ha
creado una librera de ellos?
Las libreras y frameworks son patrones de
diseo tambin?
Entonces no existen libreras de patrones de
diseo?
Recuerda
Conocer conceptos como abstraccin, herencia
y polimorfismo no te hace un diseador
orientado a objetos. Un gur en diseo piensa
en como crear diseos flexibles que sean fciles
de mantener y que puedan evolucionar con los
cambios
OO Bsico
Abstraccin
Encapsulamiento
Polimorfismo
Herencia
Principios OO
Encapsular lo que vara
Preferir composicin sobre
herencia
Programar a una interfaz, no
una implementacin
Patrones OO
Estrategia define una familia de algoritmos, encapsula cada uno de
ellos, y los hace intercambiables. Estrategia deja que los algoritmos
varen independientemente de los clientes que los utilizan
Sumario
Conocer lo bsico de OO no te hace un buen
diseador OO
Los buenos diseos OO son reusables,
extensibles y mantenibles
Patrones te ensean a crear sistemas con buenas
cualidades de diseo OO
Patrones son Experiencias comprobadas OO
Patrones no te dan cdigo sino soluciones
generales a problemas de diseo
Sumario
No fueron inventados, fueron descubiertos
Patrones y principios administran el problema
del cambio en el software
Patrones permiten que partes de un sistema
varen independientemente de otras
Buscamos tomar lo que varia en un sistema y
lo encapsulamos
Patrones provee un lenguaje compartido

Das könnte Ihnen auch gefallen