Tema 6 Patrones de Diseño Programación Orientada a Objetos Curso 2010/2011
Contenido Introducción a los patrones de diseño. Patrón del Método plantilla. Patrón Composición. Patrón Estrategia. Clases anónimas Clases internas Curso 2010/2011 Programación Orientada a Objetos 2
Introducción a los patrones de diseño Soluciones a problemas que aparecen recurrentemente en la Programación Orientada a Objetos. Diseño de clases reutilizable que se puede adaptar a diferentes situaciones. La definición de un patrón de diseño es independiente del lenguaje que se utilice para implementarlo. Vamos a estudiar: Patrón Método Plantilla. Patrón Composición. Patrón Estrategia. Curso 2010/2011 Programación Orientada a Objetos 3
Método Plantilla Define en un método el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos. Permite que las subclases implementen ciertos pasos del algoritmo sin cambiar su estructura. El algoritmo factoriza un comportamiento común a un conjunto de subclases. El algoritmo se implementa en un método efectivo que hará uso de otros métodos abstractos de la clase. Curso 2010/2011 Programación Orientada a Objetos 4
Método Plantilla Curso 2010/2011 Programación Orientada a Objetos 5
Método Plantilla Caso de Estudio En la aplicación bancaria a los titulares de los productos financieros se les envía la información fiscal. La información fiscal de un producto financiero contiene: El nombre del titular, el producto financiero contratado, el beneficio obtenido y el valor de los impuestos cobrados. El método que genera el informe fiscal es un método plantilla: Factoriza el comportamiento común a todos los productos financieros. Curso 2010/2011 Programación Orientada a Objetos 6
Método Plantilla public abstract class ProductoFinanciero { public double getimpuestos() { return getbeneficio() * 0.18; public String getinforme(){ return "Titular:" + titular + ", producto contratado: " + gettipo() + ", beneficios: " + getbeneficio() + ", impuestos: " + getimpuestos(); protected abstract String gettipo(); public abstract double getbeneficio(); Curso 2010/2011 Programación Orientada a Objetos 7
Método Plantilla Las clases hijas implementan los métodos necesarios para completar el método plantilla. public Deposito extends ProductoFinanciero { protected String gettipo() { return "Deposito"; public double getbeneficio() { return getintereses(); Curso 2010/2011 Programación Orientada a Objetos 8
Patrón Composición Permite representar objetos compuestos. Los clientes tratan de manera uniforme a los objetos individuales y a los compuestos. Curso 2010/2011 Programación Orientada a Objetos 9
Patrón Composición Caso de estudio Supongamos que en el banco existen carteras de negocios. Una cartera de negocios es un producto financiero. Una cartera de negocios puede está formada por otros productos financieros y también otras carteras. Una cartera de negocios es un producto financiero compuesto: El beneficio es la suma de los beneficios de todos los productos que contiene. Curso 2010/2011 Programación Orientada a Objetos 10
Patrón Composición Curso 2010/2011 Programación Orientada a Objetos 11
Patrón Composición public class CarteraNegocio extends ProductoFinanciero { private List<ProductoFinanciero> productos; public CarteraNegocio(Persona titular){ super(titular); productos = new LinkedList<ProductoFinanciero>(); public void addproducto(productofinanciero p) { productos.add(p); public void removeproducto(productofinanciero p) { productos.remove(p); Curso 2010/2011 Programación Orientada a Objetos 12
Patrón Composición public class CarteraNegocio extends ProductoFinanciero { @Override public double getbeneficio() { double total = 0; // El beneficio es la suma de los beneficios // de sus componentes for (ProductoFinanciero producto : productos) total += producto.getbeneficio(); return total; Curso 2010/2011 Programación Orientada a Objetos 13
Patrón Estrategia Permite definir una familia de algoritmos que se pueden intercambiar en tiempo de ejecución Ejemplos: algoritmos de ordenación, criterios de selección, etc. Favorece la extensibilidad (definición de nuevos algoritmos) Curso 2010/2011 Programación Orientada a Objetos 14
Patrón Estrategia Caso de Estudio En la aplicación bancaria, supongamos que la clase Banco almacena la lista de todos los productos financieros. Cómo podemos implementar un método de búsqueda que devuelva todos los productos financieros que cumplen una determinada condición? La condición de búsqueda puede cambiar de una búsqueda a otra: Todos los depósitos con el capital mayor que 10000 Todos los productos contratados por Juan González La estrategia se debe pasar como parámetro al método de búsqueda En Java no es posible pasar un método como parámetro. Curso 2010/2011 Programación Orientada a Objetos 15
Aplicación del Patrón Estrategia La interfaz Criterio encapsula el algoritmo que representa el criterio de búsqueda. El método test evalúa si el ProductoFinanciero que se le pasa como parámetro cumple o no el criterio de búsqueda. Cada criterio de búsqueda se implementa en una clase que implementa la interfaz Criterio. Curso 2010/2011 Programación Orientada a Objetos 16
Implementación Patrón Estrategia public interface Criterio { boolean test(productofinanciero producto); public class Banco { private List<ProductoFinanciero> productos; public List<ProductoFinanciero> buscar (Criterio criterio){ List<ProductoFinanciero> resultado = new LinkedList<ProductoFinanciero>(); for (ProductoFinanciero p: productos) if (criterio.test(p)) resultado.add(p); return resultado; Curso 2010/2011 Programación Orientada a Objetos 17
Implementación Patrón Estrategia public class CapitalAlto implements Criterio { private double umbral; public CapitalAlto(double umbral){ this.umbral = umbral; public boolean test(productofinanciero producto) { if (producto instanceof Deposito){ Deposito deposito = (Deposito)producto; return deposito.getcapital() > umbral; else return false; Curso 2010/2011 Programación Orientada a Objetos 18
Implementación Patrón Estrategia Para buscar los productos que cumplen un determinado criterio de búsqueda habrá que pasar como parámetro al método buscar un objeto de una clase que implemente el criterio. Banco banco = new Banco(); List<ProductoFinanciero> depositosaltos; Criterio criterio = new CapitalAlto(10000.0); depositosaltos = banco.buscar(criterio); Curso 2010/2011 Programación Orientada a Objetos 19
Patrón Estrategia En el caso de estudio las estrategias se establecen como parámetro de un método. La estrategia también puede almacenarse en un atributo: Este atributo puede ser inicializado en la construcción del objeto con una estrategia. Se podría establecer en cualquier momento con un método set. La interfaz Comparator es una estrategia de comparación que se pasa como parámetro en el constructor de TreeSet y se almacena como atributo. Otro caso es que la estrategia sea solicitada a los subtipos a través de un método abstracto. Curso 2010/2011 Programación Orientada a Objetos 20
Implementación Patrón Estrategia Al crear un conjunto ordenado (TreeSet) se puede establecer el criterio de ordenación en el constructor. El criterio de ordenación viene definido por la interfaz Comparator<T>. La estrategia se guarda como un atributo de TreeSet. Curso 2010/2011 Programación Orientada a Objetos 21
Implementación Patrón Estrategia La estrategia se almacena como atributo. public class Banco { private Criterio criterio; public void setcriterio(criterio criterio) { this.criterio = criterio; public List<ProductoFinanciero> filtrar (){ for (ProductoFinanciero p: productos) if (this.criterio.test(p)) resultado.add(p); return resultado; Curso 2010/2011 Programación Orientada a Objetos 22
Implementación Patrón Estrategia La estrategia la establecen los subtipos public abstract class Banco { protected abstract Criterio getcriterio(); public List<ProductoFinanciero> filtrar (){ for (ProductoFinanciero p: productos) if (getcriterio().test(p)) resultado.add(p); return resultado; Curso 2010/2011 Programación Orientada a Objetos 23
Estrategias anónimas Tiene sentido crear una clase por cada criterio? Solución basada en clases anónimas. banco.buscar( new Criterio(){ public boolean test (ProductoFinanciero p){ if (p instanceof Deposito){ Deposito deposito = (Deposito)p; return deposito.getcapital() > 10000.0; else return false; ); Curso 2010/2011 Programación Orientada a Objetos 24
Estrategias anónimas Una clase anónima define una clase en un punto del código y crea un objeto de ella. Las clases anónimas no pueden tener constructores, sólo el constructor por defecto. Una clase anónima puede acceder a información del contexto (variables y parámetros) si éstos se declaran con el modificador final. Una clase anónima es un tipo de clase interna. Curso 2010/2011 Programación Orientada a Objetos 25
Estrategias anónimas Solución basada en clases anónimas que necesita un parámetro. public List<ProductoFinanciero> buscarumbral (final double umbral){ return buscar(new Criterio(){ public boolean test(productofinanciero producto) { if (producto instanceof Deposito){ Deposito deposito = (Deposito)producto; return deposito.getcapital() > umbral; else return false; ); Curso 2010/2011 Programación Orientada a Objetos 26
Clases Internas Clase que se declara dentro de otra. Los objetos de la clase interna están ligados al objeto de la clase contenedora donde se crean: La clase interna tiene visibilidad sobre las declaraciones de la clase contenedora. Los objetos de la clase interna pueden acceder a los atributos y métodos del objeto contenedor como si fueran propios. Los objetos de la clase interna se crean dentro de un método de instancia de la clase que los contiene. Curso 2010/2011 Programación Orientada a Objetos 27
Implementación de un iterador public class Lista<T> implements Iterable<T>{ public Iterator<T> iterator() { return new Itr(); private class Itr implements Iterator<T> { private int cursor = 0; public boolean hasnext() { return cursor!= size(); public T next() { return get(cursor); public void remove() { Curso 2010/2011 Programación Orientada a Objetos 28
Clases internas El objeto iterador (clase interna Itr) se crea en el método iterator de la clase contenedora (clase Lista). Implícitamente, cuando se crea el iterador se establece una referencia a la clase Lista. El iterador tiene acceso a los métodos de la lista (size, get) En realidad la llamada size() equivale a Lista.this.size() Curso 2010/2011 Programación Orientada a Objetos 29
Clases internas anónimas Una clase anónima puede implementar una interfaz (ejemplo del patrón estrategia) o heredar de una clase: public class MarcadorAutomatico extends Marcador { public MarcadorAutomatico(int periodo) { this.periodo = periodo; TimerTask tarea = new TimerTask() { public void run() { incrementar(); ; timer = new Timer(); timer.schedule(tarea, 0, periodo); Curso 2010/2011 Programación Orientada a Objetos 30