Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Workshop Patrones de Diseño

No description
by

Federico Luppi

on 12 December 2012

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Workshop Patrones de Diseño

¿Qué son? Usos Workshop - Patrones de Diseño Un patrón de diseño resulta ser una solución a un problema de diseño. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reutilizable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.
Los Patrones de diseño comunes pueden ser mejorados a lo largo del tiempo, haciéndolos más robustos que diseños ad-hoc. Tipos Singleton Creacionales Estos patrones son aquellos que tratan con mecanismos de creación de objetos, tratando de crear los objetos en una manera adecuada para la situación.

La forma básica de creación de objetos puede resultar en problemas de diseño o complejidad agregada al diseño.

Los patrones de diseño creacionales resuelven el problema controlando de alguna manera esta creación de objetos. Estructurales Son aquellos patrones que facilitan el diseño al identificar una simple manera de realizar relaciones entre entidades

Los patrones estructurales de creación de clases usan herencia para componer interfaces.

Los patrones estructurales de creación de objetos definen maneras de componer objetos para obtener nuevas funcionalidades. Comportamiento En ingeniería de software. los patrones de diseño de comportamiento son aquellos que identifican patrones comunes de comunicación entre objetos.

Haciendo esto, se aumenta la flexibilidad en la realización de esta comunicación. El patrón de diseño singleton está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.

Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.

Singleton se implementa creando en nuestra clase un método que crea una instancia del objeto sólo si todavía no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor (con atributos como protegido o privado).

Las situaciones más habituales de aplicación de este patrón son aquellas en las que dicha clase controla el acceso a un recurso físico único (como puede ser el ratón o un archivo abierto en modo exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos de la aplicación. Ejemplo public class Singleton {
private static Singleton INSTANCE = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return INSTANCE;
}
} La instrumentación del patrón puede ser delicada en programas con múltiples hilos de ejecución. Si dos hilos de ejecución intentan crear la instancia al mismo tiempo y esta no existe todavía, sólo uno de ellos debe lograr crear el objeto. public class Singleton {
private static Singleton INSTANCE = null;

private Singleton() {}

private synchronized static void createInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}

public static Singleton getInstance() {
createInstance();
return INSTANCE;
}
} Factory Este patrón provee la encapsulación de la creación objetos de una familia a una clase. De esta manera, también se permite crear objetos sin exponer la lógica de instanciación al cliente y se deja un sólo punto de acceso para crear estos tipos de objetos.

De acuerdo a un identificador (Ya sea un id, un tipo u otro tipo de distinción), la clase Factory determinará qué tipo de objeto debe instanciar, inicializar y devolver. Ejemplo public class ProductFactory{
public static Product createProduct(String ProductID){
if (id==ID1)
return new OneProduct();
if (id==ID2)
return new AnotherProduct();

return null;
}

} Creacionales Builder Permite a un objeto cliente construir un objeto complejo especificando solamente su tipo y contenido. El cliente es privado de los detalles de construcción del objeto. Separa la construcción de un objeto complejo de su representación, para que el mismo proceso de construcción permita crear varias representaciones.
La intención de este patrón no es más que la de abstraer el proceso de creación de un objeto complejo, centralizando dicho proceso en un único punto, de tal forma que el mismo proceso de construcción pueda crear representaciones diferentes.
Clases que participan en la estructura del patrón:

Builder
Define una interfaz abstracta para crear productos.

ConcreteBuilder
Implementación de la interfaz Builder.
Construye y reúne las partes necesarias para construir los productos.

Director
Construye un objeto usando la interfaz Builder.

Producto
El objeto bajo construcción.
Métodos Propios. Ejemplo Prototype El patrón de diseño Prototype (Prototipo), tiene como finalidad crear nuevos objetos duplicándolos, clonando una instancia creada previamente.
Este patrón especifica la clase de objetos a crear mediante la clonación de un prototipo que es una instancia ya creada. La clase de los objetos que servirán de prototipo deberá incluir en su interfaz la manera de solicitar una copia, que será desarrollada luego por las clases concretas de prototipos. Ejemplo Strategy Con este patrón, se define una familia de algoritmos, los cuales son encapsulados y se hacen intercambiables. De esta manera, se permite que el algoritmo varíe independientemente del cliente que lo utiliza.

Por ejemplo, una clase que realiza validaciones de datos puede usar un patrón de estrategia para elegir el algoritmo de validación según en el tipo de datos, la fuente de los datos, a elección del usuario, etc. Estos factores no son sabidos hasta el momento de la ejecución, y pueden requerir diferentes tipos de validaciones. Las estrategias de validación, encapsuladas y separadas del objeto de validación, pueden ser usadas por otros objetos de validación en diferentes áreas del sistema sin requerir a la duplicación de código. Ejemplo interface IStrategy {
int execute(int a, int b);
}


class ConcreteStrategyAdd implements IStrategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyAdd's execute()");
return a + b; // Do an addition with a and b
}
}

class ConcreteStrategySubtract implements IStrategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategySubtract's execute()");
return a - b; // Do a subtraction with a and b
}
}

class ConcreteStrategyMultiply implements IStrategy {

public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyMultiply's execute()");
return a * b; // Do a multiplication with a and b
}
}


class Context {

private IStrategy strategy;

// Constructor
public Context(IStrategy strategy) {
this.strategy = strategy;
}

public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}


class StrategyExample {

public static void main(String[] args) {

Context context;

context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);

context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);

context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);

System.out.println("Result A : " + resultA );
System.out.println("Result B : " + resultB );
System.out.println("Result C : " + resultC );
}
} State En determinadas ocasiones, cuando el contexto en el que se está desarrollando requiere que un objeto tenga diferentes comportamientos según el estado en que se encuentra, resulta complicado poder manejar el cambio de comportamientos y los estados de dicho objeto, todos dentro del mismo bloque de código. El patrón State propone una solución a esta complicación, creando básicamente, un objeto por cada estado posible del objeto que lo llama.

Se implementa una clase para cada estado diferente del objeto y el desarrollo de cada método según un estado determinado. El objeto de la clase a la que le pertenecen dichos estados resuelve los distintos comportamientos según su estado, con instancias de dichas clases de estado. Así, siempre tiene presente en un objeto el estado actual y se comunica con este para resolver sus responsabilidades. Ejemplo Comportamiento Iterator El patrón Iterador es un mecanismo de acceso a los elementos que constituyen una estructura de datos para la utilización de estos sin exponer su estructura interna.

Motivación:
El patrón surge del deseo de acceder a los elementos de un contenedor de objetos (por ejemplo, una lista) sin exponer su representación interna. Además, es posible que se necesite más de una forma de recorrer la estructura siendo para ello necesario crear modificaciones en la clase.
La solución que propone el patrón es añadir métodos que permitan recorrer la estructura sin referenciar explícitamente su representación. La responsabilidad del recorrido se traslada a un objeto iterador.
El problema de introducir este objeto iterador reside en que los clientes necesitan conocer la estructura para crear el iterador apropiado.
Esto se soluciona generalizando los distintos iteradores en una abstracción y dotando a las estructuras de datos de un método de fabricación que cree un iterador concreto.

Las entidades participantes en el diseño propuesto por el patrón iterador son:

Iterador (Iterator) define la interfaz para recorrer el agregado de elementos y acceder a ellos, de manera que el cliente no tenga que conocer los detalles y sea capaz de manejarlos de todos modos.
Iterador Concreto (ConcreteIterator) implementa la interfaz propuesta por el Iterador. Es el que se encarga de mantener la posición actual en el recorrido de la estructura.
Agregado (Aggregate) define la interfaz para el método de fabricación de iteradores.
Agregado Concreto (ConcreteAggregate) implementa la estructura de datos y el método de fabricación de iteradores que crea un iterador específico para su estructura. Ejemplo Observer Para tener una visión actualizada de los datos, las aplicaciones de gestión, la gran mayoría de las veces, implementan esperas activas, lo cual puede bajar el rendimiento del sistema.
El esquema tradicional de solución a este problema es hacer que la aplicación periódicamente se actualice realizando pedidos a la fuente de datos, que puede ser una colección en memoria RAM o en disco duro.
Intención:
Mantener distintos objetos relacionados, relaciones uno-a-muchos (1 : N).
Mantener las dependencias entre objetos, sin necesidad de conocer al otro objeto.
Definición – Solución:
Patrón de Comportamiento para objetos.
El patrón Observador define una dependencia del tipo uno-a-muchos (1: n) entre objetos, de manera que cuando el objeto 1 cambia su estado, el observador se encarga de notificar este cambio a todos los n objetos dependientes para que se actualicen automáticamente.
El observador no es un mediador entre los sujetos (objetos que cambian de estado) y los objetos dependientes, ya que el mismo es un objeto dependiente. El observador recibe la orden de actualizar por parte del sujeto "dominante".
Distinguimos entonces el objeto observado y los objetos observadores. El objeto observado debe mantener una relación de los objetos que le observan y una forma de notificarles. Por su parte, los objetos observadores, sean del tipo que sean, deben implementar alguna funcionalidad para actualizarse en función del nuevo estado del objeto observado.
Proporciona mecanismos para “registrar” objetos observadores en el objeto observable y notificar a aquellos cuando este sufre una notificación. Ejemplo Decorator El uso del patrón Decorator es más flexible que el uso de herencia, en el sentido de que la herencia asigna responsabilidad a clases en tiempo de compilación, mientras que el patrón Decorator las asigna en tiempo de ejecución.

Este patrón se puede utilizar cuando no es práctico especializar por subclases, porque las combinaciones de funcionalidades “explotarian” en número.

Un decorator y su componente no son idénticos. El decorator actúa en realidad como un envoltorio transparente.

Para implementar este patrón, es necesario recordar:

1.- Extender el Decorator(Abstracto) original de la clase Componente(Abstracto).
2.- En la clase Decorator, agregar un puntero al Componente como atributo.
3.- Pasar un Componente al constructor del Decorator para inicializar el puntero.
4.- En la clase del decorator "redirigir" todos los "Métodos Componente" al puntero del Componente (Que llame a sus métodos)
5.- En los Decoradores Concretos, sobreescribir cada "Método Componente" que se deba modificar su comportamiento. Private Data Class Una clase puede exponer sus atributos para ser manipulados solo en la creación del objeto pero luego no.

El diseño de datos de clase privados busca reducir la exposición de atributos a través de la limitación de su visibilidad.
Reduce el numero de atributos de clase encapsulandolos en un sólo objeto de datos. Esto permite remover permisos de escritura de los atributos que fueron destinados a ser setteados solo durante la construcción. Ejemplo Estructurales Adapter Convierte la interfaz de una clase en otra permitiendo a ambas trabajar juntas, las hace compatibles.

Un adaptador convierte una clase adapter ya existente, que presenta una no utilizable (quizás implícitamente) interfaz a otra interfaz de destino, que los componentes de otros clientes están listos para usar.
Este patrón se utiliza a menudo para integrar las diferentes partes de una aplicación, ya que mágicamente hace hablar a cada uno de las otras clases que eran extraños. Se puede considerar también para modificar las clases para mejorar su relación, pero sólo si usted es dueño de ellos y no se requiere compatibilidad con versiones anteriores, el problema principal reside en no introducir acoplamiento innecesario.

Los participantes
Cliente: hace uso de un objeto que implementa la interfaz Target.
Target: punto de extensión para el módulo del cliente.
Adaptee: objeto de un módulo diferente o biblioteca.
Adaptador: Implementación de Target que redirige al trabajo real para el adapter, a la vez totalmente escondido.
Ejemplo Composite El patrón composite es un patrón de diseño muy poderoso en si mismo, consiste en crear objetos a partir de otros mas pequeños, también puede contener objetos que tienen otros objetos, dando el aspecto de un árbol eneario.
En otras palabras, lo que afecte al objeto de mayor jerarquía alterará a todos sus objetos “hijos”, entonces, supongamos que crearemos un aplicación que contiene etiquetas y también paneles, ambos son componentes, que quiere decir esto? pues que tanto etiqueta como panel están implementan una interfaz común, por lo tanto va a tener las mismas funciones, y esto para que sirve? el panel a diferencia de una etiqueta, tiene la posibilidad de almacenar dentro de el otros componentes (mas etiquetas o mas paneles), entonces si queremos pintar todos los componentes de color rojo lo normal seria ir uno a uno pintándolo de color rojo (etiquetas y paneles), pero con el patrón composite nos evitamos esta tarea, y con una simple llamada al método pintar del componente de mayor jerarquía se pintan todos los demás componente debajo de él, vemos:
El patrón Composite sirve para construir objetos complejos a partir de otros más simples y similares entre sí, gracias a la composición recursiva y a una estructura en forma de árbol.
Esto simplifica el tratamiento de los objetos creados, ya que al poseer todos ellos una interfaz común, se tratan todos de la misma manera.

Participantes:
Cliente: envía el mensaje al componente principal.
Componente: declara la interfaz que varias partes de la gráfica debe respetar.
Hoja: clase concreta que no tiene hijos.
Composite: Clase que compone los otros componentes . Ejemplo Ejemplo http://gcoding.blogspot.com.ar/2011/01/patron-de-diseno-decorator.html El ejemplo a continuación utiliza el patrón decorator para poder capacitar a un estudiante de ingeniería en varias áreas, para luego incluirlas en su currículum. interface Statelike {

void writeName(final StateContext STATE_CONTEXT, final String NAME);
}

class StateA implements Statelike {

@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toLowerCase());
STATE_CONTEXT.setState(new StateB());
}

}

class StateB implements Statelike {
/** State counter */
private int count = 0;


@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toUpperCase());
// Change state after StateB's writeName() gets invoked twice
if(++count > 1) {
STATE_CONTEXT.setState(new StateA());
}
}

}
public class StateContext {
private Statelike myState;

public StateContext() {
setState(new StateA());
}


public void setState(final Statelike NEW_STATE) {
myState = NEW_STATE;
}


public void writeName(final String NAME) {
myState.writeName(this, NAME);
}
}
public class TestClientState {
public static void main(String[] args) {
final StateContext SC = new StateContext();

SC.writeName("Monday");
SC.writeName("Tuesday");
SC.writeName("Wednesday");
SC.writeName("Thursday");
SC.writeName("Friday");
SC.writeName("Saturday");
SC.writeName("Sunday");
}
} Para el ejemplo anterior, el output seria:
monday
TUESDAY
WEDNESDAY
thursday
FRIDAY
SATURDAY
sunday Los patrones de diseño aceleran el proceso de desarrollo al proveer paradigmas de desarrollo ya probados. Un efectivo diseño de software requiere considerar temas que pueden no ser visibles hasta tarde en la implementación. Reusar patrones de diseño ayuda a prevenir dichos temas que pueden causar problemas mayores y mejora la legibilidad del código para desarrolladores y arquitectos familiares con los patrones. Usualmente, la gente solo entiende como aplicar ciertas técnicas de diseño de software para ciertos problemas. Esas técnicas son difíciles de aplicar a un amplio rango de problemas. Los patrones de diseño proveen soluciones generales, documentadas en un formato que no requiere estar ligado a cierto problema. Ventajas Reduce el acoplamiento.
Permite variar la representación interna de estructuras compleja, respetando la interfaz común de la clase Builder.
Se independiza el código de construcción de la representación. Las clases concretas que tratan las representaciones internas no forman parte de la interfaz del Builder.
Cada ConcreteBuilder tiene el código especifico para crear y modificar una estructura interna concreta.
Distintos Director con distintas utilidades (visores, parsers, etc) pueden utilizar el mismo ConcreteBuilder.
Permite un mayor control en el proceso de creación del objeto. El Director controla la creación paso a paso, solo cuando el Builder ha terminado de construir el objeto lo recupera el Director. Este patrón resulta útil en escenarios donde es preciso abstraer la lógica que decide qué tipos de objetos utilizará una aplicación, de la lógica que luego usarán esos objetos en su ejecución. Los motivos de esta separación pueden ser variados, por ejemplo, puede ser que la aplicación deba basarse en alguna configuración o parámetro en tiempo de ejecución para decidir el tipo de objetos que se debe crear. En ese caso, la aplicación necesitará crear nuevos objetos a partir de modelos. Estos modelos, o prototipos, son clonados y el nuevo objeto será una copia exacta de los mismos, con el mismo estado. Como decimos, esto resulta interesante para crear, en tiempo de ejecución, copias de objetos concretos inicialmente fijados, o también cuando sólo existe un número pequeño de combinaciones diferentes de estado para las instancias de una clase.
Dicho de otro modo, este patrón propone la creación de distintas variantes de objetos que nuestra aplicación necesite, en el momento y contexto adecuado. Toda la lógica necesaria para la decisión sobre el tipo de objetos que usará la aplicación en su ejecución se hace independiente, de manera que el código que utiliza estos objetos solicitará una copia del objeto que necesite. En este contexto, una copia significa otra instancia del objeto. El único requisito que debe cumplir este objeto es suministrar la funcionalidad de clonarse.
En el caso, por ejemplo, de un editor gráfico, podemos crear rectángulos, círculos, etc... como copias de prototipos. Estos objetos gráficos pertenecerán a una jerarquía cuyas clases derivadas implementarán el mecanismo de clonación. Motivación ¿Cómo reconozco dónde necesito un adaptador? La necesidad de un adaptador generalmente resulta a partir de las modificaciones o mejoramientos de las bibliotecas de clases o componentes COM, Por ejemplo, re-factorizar frecuentemente puede provocar cambios significativos en la forma en que necesita ser definida la interfaz para una clase. Esto a su vez, puede provocar más cambios en el código de la aplicación que llama al servicio de su clase. Hacer los cambios es siempre una opción de alto riesgo que debe ser evitada siempre que sea posible.
Cuando el código fuente está disponible, una solución es mantener los métodos en la interfaz original a la clase; pero eliminar la implementación en los métodos nuevos. Los métodos viejos no hacen más el trabajo real, en su lugar, ellos "controlan" las llamadas a otros métodos. Sin embargo, esto requiere aún, que se modifique el código existente.
La alternativa es crear una clase nueva la cual replique la interfaz esperada y traduzca las llamadas a la interfaz en el formato correcto para reemplazarlo. Al tratar con componentes en los cuales el código no está disponible, es el único método para tratar con los cambios en su interfaz. Imaginemos que necesitamos crear una serie de clases para guardar información acerca de una serie de figuras que serán círculos, cuadrados y triángulos. Además necesitamos poder tratar también grupos de imágenes porque nuestro programa permite seleccionar varias de estas figuras a la vez para moverlas por la pantalla.
En principio tenemos las clases Círculo, Cuadrado y Triángulo, que heredarán de una clase padre que podríamos llamar Figura e implementarán todas la operación pintar(). En cuanto a los grupos de Figuras podríamos caer en la tentación de crear una clase particular separada de las anteriores llamada GrupoDeImágenes, también con un método pintar().

Problema.
Esta idea de separar en clases privadas componentes (figuras) y contenedores (grupos) tiene el problema de que, para cada uno de los dos atributos, el método pintar() tendrá una implementación diferente, aumentando la complejidad del sistema. El patrón Composite da una solución elegante a este problema, de la que además resulta en una implementación más sencilla.
A la clase Figura la llamaríamos Gráfico y de ella extenderían tanto Círculo, Cuadrado y Triángulo, como GrupoDeImágenes. Además, ésta última tendría una relación todo-parte de multiplicidad * con Gráfico: un GrupoDeImágenes contendría varios Gráficos, ya fuesen éstos Cuadrados, Triángulos, u otras clases GrupoDeImágenes.
Así, es posible definir a un grupo de imágenes recursivamente. Por ejemplo, un objeto cuya clase es GrupoDeImágenes podría contener un Cuadrado, un Triángulo y otro GrupoDeImágenes, este grupo de imágenes podría contener un Círculo y un Cuadrado. Posteriormente, a este último grupo se le podría añadir otro GrupoDeImágenes, generando una estructura de composición recursiva en árbol, por medio de muy poca codificación y un diagrama sencillo y claro. Para la creación del patrón iterador debe implementarse el control de la iteración (pudiendo ser un iterador externo que ofrece los métodos para que el cliente recorra la estructura paso a paso, o un iterador interno que ofrece un método de actuación sobre la estructura que, de manera transparente al cliente, la recorre aplicándose a todos sus elementos) y definirse el recorrido. A mayores se podrían implementar operaciones adicionales en el iterador o definir la estructura de éste de una manera más robusta ante cambios en la estructura. Hay que tener especial cuidado en la implementación de iteradores con accesos privilegiados, iteradores para estructuras compuestas o iteradores nulos. Este patrón también se conoce como el patrón de publicación-suscripción o modelo-vista. Estos nombres sugieren las ideas básicas del patrón, que son bien sencillas: el objeto de datos, llamémoslo "Sujeto" a partir de ahora, contiene métodos mediante los cuales cualquier objeto observador o vista se puede suscribir a él pasándole una referencia a sí mismo. El Sujeto mantiene así una lista de las referencias a sus observadores.

Los observadores a su vez están obligados a implementar unos métodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores "suscritos" los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto, ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno. Consideremos una interfaz de usuario en la que se poseen diferentes representaciones de determinados datos de una aplicación. Las clases que representan los datos (el modelo) y las representaciones gráficas (las vistas) pueden ser reutilizadas independientemente.

Una hoja de cálculo, un diagrama de barras y un diagrama de sectores pueden mostrar diferentes presentaciones de los datos de una aplicación, pero cada uno de esos tres objetos pueden ser utilizadas independientemente en otras aplicaciones.
Las modificaciones sobre los datos deben repercutir en las tres presentaciones, e incluso podría ocurrir que alguno de los diagramas fuese editable, y modificaciones en él también repercutirían en el resto de diagramas y en los propios datos.
Full transcript