Patrones de Software.
Ingeniería de Software.
Ingeniería de Software. Patrones de Software Página 0
Patrones de Software.
Mapa del Proceso.
Ingeniería de Software. Patrones de Software Página 1
Concepto.
• Un patrón de software es:
“A description of communicating objects and classes that are
customized to solve a general design problem in a particular
context.”
• Inspirados por patrones de arquitectura “normal” (de construcciones
físicas).
Ingeniería de Software. Patrones de Software Página 2
físicas).
• Libro de Gamma, Helm, Johnson y Vlissides (GoF) (*).
• Elementos esenciales:
• Nombre.
• Problema.
• Solución.
• Consecuencias o implicaciones.
* Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma,
Richard Helm, Ralph Johnson, and John Vlissides. Addison Wesley Professional, 1994.
Niveles de Patrones de Software.
• Patrones Arquitectónicos.
• Describen soluciones al nivel más alto de software y
hardware.
• Normalmente soportan requerimientos no funcionales.
• Por ejemplo, MVC y PAC.
• Patrones de Diseño.
Ingeniería de Software. Patrones de Software Página 3
• Patrones de Diseño.
• Describen soluciones en el nivel medio de estructuras de
software.
• Usualmente soportan requerimientos funcionales.
• Patrones de Programación (Idioms).
• Describen soluciones en el nivel de software más bajo (clases
y métodos).
• Generalmente soportan características específicas de un
lenguaje de programación.
Los Patrones GoF Originales (1).
Creacionales
1. Singleton (y Multiton)
2. Factory Method
Ingeniería de Software. Patrones de Software Página 4
3. Abstract Factory
4. Builder
5. Prototype
� Subrayado indica que se incluye explicación y ejemplo
Los Patrones GoF Originales (2).
Estructurales
6. Adapter
7. Bridge
8. Composite
Ingeniería de Software. Patrones de Software Página 5
8. Composite
9. Decorator
10. Façade
11. Flyweight
12. Proxy
� Subrayado indica que se incluye explicación y ejemplo
Los Patrones GoF Originales (3).
Conductuales
13. Chain of responsibility
14. Command
15. Intepreter
16. Iterator
19. Observer
20. State (*)
21. Strategy
22. Template Method
Ingeniería de Software. Patrones de Software Página 6
16. Iterator
17. Mediator
18. Memento
* El patrón state se estudia en el capítulo de modelado de estado de objetos
complejos.
22. Template Method
23. Visitor
� Subrayado indica que se incluye explicación y ejemplo
Los Patrones de JavaEE (1).
Presentation Tier
1. Intercepting Filter
2. Front Controller
3. Context Object
Ingeniería de Software. Patrones de Software Página 7
3. Context Object
4. Application Controller
5. View Helper
6. Composite View
7. Service To Worker
8. Dispatcher view
Los Patrones de JavaEE (2).
Business Tier
9. Business Delegate
10. Service Locator
11. Session Façade
12. Transfer Object
Ingeniería de Software. Patrones de Software Página 8
12. Transfer Object
13. Transfer Object Assembler
14. Application Service
15. Business Object
16. Composite Entity
17. Data Transfer Object
18. Value List Handler
Los Patrones de JavaEE (3).
Integration Tier
19. Data Access Object
20. ServiceActivator
21. Domain Store
Ingeniería de Software. Patrones de Software Página 9
21. Domain Store
22. Web Service Broker
El Patrón de Diseño Singleton (1).
“Idiom that is used to restrict instantiation of a class to a
one single object.”
• Es utilizado cuando se requiere exactamente un objeto para coordinar
acciones a través de una aplicación.
Ingeniería de Software. Patrones de Software Página 10
acciones a través de una aplicación.
• Existe una variante llamada Multiton que es una generalización usada
para sistemas que operan más eficientemente cuando se requieren
exactamente n objetos de una clase.
• Si se usa exageradamente, introduce limitaciones innecesarias en
situaciones cuando realmente no se requiere una sola instancia. Debe
ser usado cuidadosamente.
El Patrón de Diseño Singleton (2).
Problema:
• Un sistema tiene una clase principal.
• Debe existir una sola instancia de esta clase.
• No se quiere que otros componentes sean capaces de crear otras
instancias de la clase principal.
Ingeniería de Software. Patrones de Software Página 11
Solución:
• Declarar el constructor de la clase principal como privado.
• Crear dentro de la clase principal una instancia de ella misma.
• Proporcionar un método estático que entregue la instancia a quien
la solicite.
El Patrón de Diseño Singleton (3).
MainClass
- singleton: MainClass
- MainClass()
Ingeniería de Software. Patrones de Software Página 12
- MainClass()
<<static>>
+ getInstance(): MainClass
El Patrón de Diseño Singleton (4).
Ejemplo de Solución.
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// Private constructor prevents instantiation from other classes
private Singleton() { }
public static Singleton getInstance() {
Ingeniería de Software. Patrones de Software Página 13
public static Singleton getInstance() {
return INSTANCE;
}
}
public class Componente {
private Singleton myInstance = new Singleton(); // inválido
private Singleton myInstance = Singleton.getInstance() ; // ok
}
“Define an interface for creating an object, but let the
subclasses decide which class to instantiate. The Factory
method lets a class defer instantiation to subclasses.”
El Patrón de Diseño Factory Method.
Ingeniería de Software. Patrones de Software Página 14
• Define un método separado cuya función es la creación de objetos.
• No es necesario especificar la clase exacta de la que proviene el objeto creado.
• Las subclases pueden hacer un override para especificar el tipo derivado del objeto que crean.
• Más generalmente, el término Factory Method se emplea para cualquier método cuyo propósito principal es la creación de objetos.
Problema:
• No existe un mecanismo simple para crear objetos sin especificar
su clase exacta.
El Patrón de Diseño Factory Method (2).
Ingeniería de Software. Patrones de Software Página 15
Solución:
• Crear una clase Factory que tiene un método createXXX.
• Las clases que deseen crear objetos de clase Factory deben utilizar
el método createXXX.
El Patrón de Diseño Factory Method (3).
Ingeniería de Software. Patrones de Software Página 16
El Patrón de Diseño Factory Method (4).
Consecuencias:
• +• Se pueden agregar subclases de productos en
forma transparente.
Ingeniería de Software. Patrones de Software Página 17
forma transparente.
• Proporciona un mecanismo standard de creación
de objetos.
• -• Overhead en el proceso comparado con new()
simple.
public abstract class Pizza {
public abstract double getPrice();
}
El Patrón de Diseño Factory Method (5).
Ingeniería de Software. Patrones de Software Página 18
public class HamAndMushroomPizza extends Pizza {
private double price = 8.5;
public double getPrice() {
return price;
}
}
public class DeluxePizza extends Pizza {
private double price = 10.5;
public double getPrice() {
return price;
}
El Patrón de Diseño Factory Method (6).
Ingeniería de Software. Patrones de Software Página 19
}
}
public class HawaiianPizza extends Pizza {
private double price = 11.5;
public double getPrice() {
return price;
}
}
public class PizzaFactory {
public enum PizzaType {
HamMushroom, Deluxe, Hawaiian
}
public static Pizza createPizza(PizzaType pizzaType) {
switch (pizzaType) {
El Patrón de Diseño Factory Method (7).
Ingeniería de Software. Patrones de Software Página 20
switch (pizzaType) {
case HamMushroom: return new HamAndMushroomPizza();
case Deluxe: return new DeluxePizza();
case Hawaiian: return new HawaiianPizza();
}
System.out.println ("The pizza type “+pizzaType+“ is not recognized.");
return null;
}
}
public class PizzaLover {
public static void main (String args[ ]) {
for(PizzaFactory.PizzaType pizzaType: PizzaFactory.PizzaType.values() ) {
System.out.println("Price of " + pizzaType + " is " +
El Patrón de Diseño Factory Method (8).
Ingeniería de Software. Patrones de Software Página 21
System.out.println("Price of " + pizzaType + " is " +
PizzaFactory.createPizza(pizzaType).getPrice());
}
}
}
El Patrón de Diseño Abstract Factory (1).
“Provide an interface for creating families of related or
dependent objects without specifying their concrete classes.”
• Proporciona una manera de encapsular un grupo de fábricas individuales
que tienen un tema común.
• En el uso normal, el cliente crea una implementación concreta de la
Ingeniería de Software. Patrones de Software Página 22
• En el uso normal, el cliente crea una implementación concreta de la
Abstract Factory y usa las intefaces genéricas que crean los objetos
concretos que son parte del tema común.
• El cliente no sabe (ni le interesa) que objetos concretos obtiene de cada
una de las fábricas internas puesto que sólo usa las interfaces genéricas
para crear sus productos.
• Normalmente se implementa usando Factory Method.
El Patrón de Diseño Abstract Factory (2).
Problema:
• Un sistema consta de varias familias de productos.
• Cada familia está diseñada para ser usada como un todo.
• No se quieren revelar las clases que implementan las familias.
Ingeniería de Software. Patrones de Software Página 23
Solución:
• Crear una clase abstracta o interfaz, AbstractFactory que tiene un
método createXXX para cada tipo de producto.
• Crear una clase concreta, ConcreteFactoryN que implemente los
métodos createXXX para cada tipo de producto y que entregue un
producto concreto.
El Patrón de Diseño Abstract Factory (3).
Ingeniería de Software. Patrones de Software Página 24
El Patrón de Diseño Abstract Factory (4).
Consecuencias:
• +• Aísla las clases concretas (principio de
inversión de la Dependencia).
• Facilita intercambiar familias de productos.
Ingeniería de Software. Patrones de Software Página 25
• Facilita intercambiar familias de productos.
• Promueve la consistencia entre productos.
• -• Es difícil soportar nuevas clases de productos.
Ejemplo de Abstract Factory (1).
/* GUIFactory example -- */
public interface GUIFactory {
public Button createButton();
}
public class WinFactory implements GUIFactory {
public Button createButton() {
Ingeniería de Software. Patrones de Software Página 26
public Button createButton() {
return new WinButton();
}
}
public class LinuxFactory implements GUIFactory {
public Button createButton() {
return new LinuxButton();
}
}
Ejemplo de Abstract Factory (2).
public interface Button {
public void paint();
}
public class WinButton implements Button {
public void paint() {
System.out.println("I'm a WinButton"); }
}
public class LinuxButton implements Button {
Ingeniería de Software. Patrones de Software Página 27
public class LinuxButton implements Button {
public void paint() {
System.out.println("I'm a LinuxButton");
}
}
public class Application {
public Application(GUIFactory factory) {
Button button = factory.createButton();
button.paint();
}
}
Ejemplo de Abstract Factory (3).
public class ApplicationRunner {
private static String OS = "Win";
public static void main(String[ ] args) {
if (args.length != 0) { OS = args[0]; }
else { OS = "Win"; }
new Application(createOsSpecificFactory());
}
Ingeniería de Software. Patrones de Software Página 28
}
public static GUIFactory createOsSpecificFactory() {
if (OS.equals("Win")) {
return new WinFactory();
} else {
return new LinuxFactory();
}
}
}
El Patrón de Diseño Composite (1).
“Compose objects into tree structures to represent part-whole
hierarchies. Composite lets clients treat individual objects and
compositions of objects uniformly.”
Ingeniería de Software. Patrones de Software Página 29
• Composite permite que un grupo de objetos sean tratados de la misma
manera que cada elemento del grupo.
• El intento de composite es integrar objetos en estructuras tipo árbol que
representen las jerarquías del todo (compuesto) y las partes.
• Composite permite a los clientes tratar objetos individuales y compuestos
de esos objetos uniformemente.
El Patrón de Diseño Composite (2).
Problema:
• Se quieren representar jerarquías de objetos de tipo parte y
compuestos.
• Se quiere usar la misma interfaz en las partes y en los compuestos.
Ingeniería de Software. Patrones de Software Página 30
Solución:
• Crear una interfaz o clase abstracta, Component, que actúe como
superclase de las clases concretas que representan las partes y los
compuestos.
• Las clases que representan los compuestos pueden ser tratadas
como partes, porque soportan la interfaz Component.
El Patrón de Diseño Composite (3).
Estilo original:
Ingeniería de Software. Patrones de Software Página 31
El Patrón de Diseño Composite (4).
Estilo alterno:
Ingeniería de Software. Patrones de Software Página 32
El Patrón de Diseño Composite (5).
Consecuencias:
• +• Hace el cliente simple.
• Facilita la agregación de nuevos tipos de
Ingeniería de Software. Patrones de Software Página 33
• Facilita la agregación de nuevos tipos de
componentes
• -• Puede hacer el modelo de diseño
demasiado general.
Ejemplo de Composite (1).
// Interfaz general
import java.util.List;
import java.util.ArrayList;
public interface Graphic {
// Prints the graphic.
public void print();
}
// Composite
Ingeniería de Software. Patrones de Software Página 34
// Composite
import java.util.*;
public class CompositeGraphic implements Graphic {
// Collection of child graphics.
private List<Graphic> mChildGraphics = new ArrayList<Graphic>();
// Prints the graphic.
public void print() {
for (Graphic graphic : mChildGraphics) {
graphic.print();
}
Ejemplo de Composite (2).
// Adds the graphic to the composition.
public void add(Graphic graphic) {
mChildGraphics.add(graphic);
}
// Removes the graphic from the composition.
public void remove(Graphic graphic) {
mChildGraphics.remove(graphic);
Ingeniería de Software. Patrones de Software Página 35
mChildGraphics.remove(graphic);
}
}
// Leaf
public class Ellipse implements Graphic {
// Prints the graphic.
public void print() {
System.out.println("Ellipse");
}
}
Ejemplo de Composite (3).
// Client
public class Program {
public static void main(String[] args) {
// Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ingeniería de Software. Patrones de Software Página 36
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
// Initialize three composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
// Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
Ejemplo de Composite (4).
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(graphic1);
graphic.add(graphic2);
Ingeniería de Software. Patrones de Software Página 37
graphic.add(graphic2);
// Prints the complete graphic (four times the string "Ellipse").
graphic.print();
}
}
El Patrón de Diseño Façade (1).
“A façade is an object that provides a simplified interface to a larger
body of code, such as a class library. ”
• Logra que un conjunto de clases de software sea más fácil de usar y
entender puesto que proporciona métodos homogéneos para tareas
comunes.
Ingeniería de Software. Patrones de Software Página 38
• Hace que el código que usa las clases sea más claro y legible.
• Reduce dependencias de código exterior en el código del conjunto de
clases puesto que la mayoría del código usa la fachada, lo cual permite
mayor flexibilidad en el desarrollo del sistema.
• Encapsula una colección de APIs diseñadas pobremente en una sola
API bien diseñada.
El Patrón de Diseño Façade (2).
Problema:
• Se tienen una serie de clases que hacen funciones similares pero
que tienen métodos diferentes.
• Las clases no están diseñadas homogéneamente.
Ingeniería de Software. Patrones de Software Página 39
Solución:
• Crear una clase Façade que incluya las diferentes clases como
atributos.
• Hacer que los clientes utilicen la clase Façade en vez de las
clases independientes.
El Patrón de Diseño Façade (3).
Ingeniería de Software. Patrones de Software Página 40
El Patrón de Diseño Façade (4).
Consecuencias:
• +• Mantiene el cliente simple y limpio.
• Reduce la complejidad de acceso a subsistemas.
Ingeniería de Software. Patrones de Software Página 41
• Reduce la complejidad de acceso a subsistemas.
• Permite la reutilización de sistemas legado con una nueva
interfaz.
• -• Mayor número de clases.
• Difícil de probar.
Ejemplo de Façade (1).
// Complex parts
public class CPU {
public void freeze() { ... }
public void jump(long position) { ... }
public void execute() { ... }
}
public class Memory {
public void load(long position, byte[ ] data) { ... }
}
Ingeniería de Software. Patrones de Software Página 42
}
public class HardDrive {
public byte[ ] read(long lba, int size) { ... }
}
public class Computer { // Façade
public void startComputer( ) {
cpu.freeze();
memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR,SECTOR_SIZE));
cpu.jump(BOOT_ADDRESS);
cpu.execute();
}
}
Ejemplo de Façade (2).
// Client
public class User {
public static void main(String[ ] args) {
Computer facade = new Computer();
facade.startComputer();
}
}
Ingeniería de Software. Patrones de Software Página 43
}
El Patrón de Diseño Strategy (1).
“Define a family of algorithms, encapsulate each one, and make
them interchangeable. Strategy lets the algorithm vary
independently from clients that use it.”
• Es utilizado en situaciones donde es necesario intercambiar
dinámicamente los algoritmos usados en una aplicación.
Ingeniería de Software. Patrones de Software Página 44
dinámicamente los algoritmos usados en una aplicación.
• Su función es proporcionar un medio para definir una familia de
algoritmos, encapsular cada uno de ellos como un objeto y hacerlos
intercambiables.
• Permite que los algoritmos varíen independientemente de los clientes que
los utilicen.
• A Strategy is an object that represents an algorithm.
El Patrón de Diseño Strategy (2).
Problema:
• Se tiene un conjunto de clases que sólo difieren en los algoritmos
que usan.
• Se quiere cambiar de algoritmo en el momento de la ejecución.
Ingeniería de Software. Patrones de Software Página 45
Solución:
• Crear una interfaz, Strategy, que sea implementada por un
conjunto de clases concretas.
• En tiempo de ejecución, seleccionar una instancia de estas clases
particulares dentro de otra clase Context, que contiene referencias
a la interfaz Strategy.
El Patrón de Diseño Strategy (3).
Ingeniería de Software. Patrones de Software Página 46
El Patrón de Diseño Strategy (4).
Consecuencias:
• +• Alternativa a usar subclases.
• Elimina postulados condicionales en la
Ingeniería de Software. Patrones de Software Página 47
• Elimina postulados condicionales en la
implementación.
• -• Overhead entre Strategy y Context.
• Se incrementa el número de objetos.
Ejemplo de Strategy (1).
// The classes that implement a concrete strategy should implement this.
// The context class uses this to call the concrete strategy
public interface Strategy {
int execute(int a, int b);
}
Ingeniería de Software. Patrones de Software Página 48
}
// Implements the algorithm using the strategy interface
public class ConcreteStrategyAdd implements Strategy {
public int execute(int a, int b) {
System.out.print("Called ConcreteStrategyA's execute() ");
return (a + b);
}
}
Ejemplo de Strategy (2).
public class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
System.out.print("Called ConcreteStrategyB's execute() ");
return (a - b);
}
Ingeniería de Software. Patrones de Software Página 49
}
public class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
System.out.print("Called ConcreteStrategyC's execute() ");
return a * b;
}
}
Ejemplo de Strategy (3).
// Configured with a ConcreteStrategy object and maintains a reference to a
// Strategy object
public class Context {
Strategy strategy;
public Context(Strategy strategy) {
Ingeniería de Software. Patrones de Software Página 50
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int execute(int a, int b) {
return strategy.execute(a, b);
}
}
Ejemplo de Strategy (4).
public class StrategyExample {
public static void main(String[ ] args) {
Context context;
// Three contexts following different strategies
context = new Context(new ConcreteStrategyAdd());
int resultA = context.execute(3,4);
System.out.println(resultA);
Ingeniería de Software. Patrones de Software Página 51
System.out.println(resultA);
context = new Context(new ConcreteStrategySubtract());
int resultB = context.execute(3,4);
System.out.println(resultB);
context = new Context(new ConcreteStrategyMultiply());
int resultC = context.execute(3,4);
System.out.println(resultC);
}
}
El Patrón de Diseño Observer (1).
“Define a one-to-many dependency between objects so that
when one object changes, all its dependents are notified and
updated automatically.”
• En este patrón, un objeto llamado el subject u observable, mantiene una
Ingeniería de Software. Patrones de Software Página 52
• En este patrón, un objeto llamado el subject u observable, mantiene una
lista de sus dependientes, llamados observers.
• El subject notifica a sus observadores de cualquier cambio en su
estado.
• La notificación normalmente es mediante llamados a un método especial
de los observadores.
El Patrón de Diseño Observer (2).
Problema:
• Se necesita notificar a un conjunto de objetos que ha ocurrido un
evento.
• El conjunto de objetos puede cambiar en el momento de la
ejecución.
Ingeniería de Software. Patrones de Software Página 53
ejecución.
Solución:
• Crear una clase abstracta, Subject, que mantenga una colección
de objetos Observer.
• Cuando ocurre un cambio, se notifica a todos los observadores.
El Patrón de Diseño Observer (3).
Ingeniería de Software. Patrones de Software Página 54
El Patrón de Diseño Observer (4).
Consecuencias:
• +• Acoplamiento abstracto entre Subject y Observer.
• Soporte para notificaciones en modo multicast.
Ingeniería de Software. Patrones de Software Página 55
• Soporte para notificaciones en modo multicast.
• -• Actualizaciones no esperadas en los
observadores.
Ejemplo de Observer (1).
import java.util.Observable;
import java.io.*
public class EventSource extends Observable implements Runnable { // Subject
public void run() {
try {
final InputStreamReader isr = new InputStreamReader( System.in );
final BufferedReader br = new BufferedReader( isr );
Ingeniería de Software. Patrones de Software Página 56
final BufferedReader br = new BufferedReader( isr );
while( true ) {
final String response = br.readLine();
setChanged(); // implementado en la clase Observable
notifyObservers(response); // implementado en la clase Observable
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ejemplo de Observer (2).
import java.util.Observable;
import java.util.Observer;
public class ResponseHandler implements Observer { // Observer
private String resp;
public void update (Observable obj, Object arg) {
if (arg instanceof String) {
Ingeniería de Software. Patrones de Software Página 57
resp = (String) arg;
System.out.println("\nReceived Response: "+ resp );
}
}
}
Ejemplo de Observer (3).
public class MyApp {
public static void main(String args[ ]) {
System.out.println("Enter Text >");
// create an event source - reads from stdin
final EventSource evSrc = new EventSource();
// create an observer final
ResponseHandler respHandler = new ResponseHandler() ;
Ingeniería de Software. Patrones de Software Página 58
ResponseHandler respHandler = new ResponseHandler() ;
// subscribe the observer to the event source
evSrc.addObserver( respHandler );
// starts the event thread
Thread thread = new Thread(evSrc);
thread.start();
}
}
Ejercicio.
• Presentar los siguientes patrones por equipo:
Patrón Equipo Patrón Equipo
Prototype 7 Interpreter 10
Ingeniería de Software. Patrones de Software Página 59
Builder 2 Bridge 3
Adapter 5 Mediator 8
Command 9 Template Method 4
Iterator 6 Visitor 1
Tarea (continuación).
• Contenido de la presentación:
o Descripción general del patrón.
o Problema.
o Solución.
Ingeniería de Software. Patrones de Software Página 60
o Solución.
o Diagrama de clases.
o Consecuencias positivas y negativas.
o Ejemplo.
• Desarrolladas en PowerPoint.