Craig Larman, “Applying UML and...

23
Design Patterns Franco Guidi Polanco Escuela de Ingeniería Industrial Pontificia Universidad Católica de Valparaíso, Chile [email protected] Franco Guidi Polanco 2 Introducción El uso de un martillo no lo convierte a uno en arquitecto” - Proverbio … y en lo que nos concierne… “Conocer un lenguaje orientado a objetos (como Java) es necesario, pero insuficiente para crear sistemas orientados a objetos” - Craig Larman, “Applying UML and Patterns” Franco Guidi Polanco 3 ? El diseño del software Diseñar software orientado a objetos no es una actividad sencilla. Los desarrolladores experimentados hacen mejores diseños de software que aquellos inexpertos. ¿Qué saben los primeros, que no saben los segundos? Franco Guidi Polanco 4 Los patrones de diseño Los diseñadores expertos saben que no conviene construir un sistema desde cero. Es más conveniente reutilizar soluciones que han funcionado bien en el pasado. Esto es, cuando encuentran una buena solución, la reutilizan, una y otra vez… .., y otra, y otra, y otra y otra, y otra, y otra….

Transcript of Craig Larman, “Applying UML and...

Page 1: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Design Patterns

Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

Franco Guidi Polanco 2

Introducción

“El uso de un martillo no lo convierte a uno en arquitecto”

- Proverbio

… y en lo que nos concierne…

“Conocer un lenguaje orientado a objetos (como Java) es necesario, pero insuficiente para crear

sistemas orientados a objetos”- Craig Larman, “Applying UML and Patterns”

Franco Guidi Polanco 3

?

El diseño del software

Diseñar software orientado a objetos no es una actividad sencilla.Los desarrolladores experimentados hacen mejores diseños de software que aquellos inexpertos.

¿Qué saben los primeros, que no saben los segundos?

Franco Guidi Polanco 4

Los patrones de diseño

Los diseñadores expertos saben que no conviene construir un sistema desde cero.Es más conveniente reutilizar soluciones que han funcionado bien en el pasado.Esto es, cuando encuentran una buena solución, la reutilizan, una y otra vez…

.., y otra, y otra, y otra y otra, y otra, y otra….

Page 2: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 5

Los patrones de diseño

.., y otra,

y otra, y otra,

y otra, y otra,

y otra….

Franco Guidi Polanco 6

Los patrones de diseño

Es, entonces, esta “experiencia” la que ayuda a los diseñadores a convertirse en “expertos”.Cabe preguntarse:

?¿existirá alguna forma de

registrar esta experiencia y comunicarlaa otros?

Franco Guidi Polanco 7

Christopher Alexander

Arquitecto (de casas y edificios).Publicó el libro A PatternLanguage (1977), donde describe un conjunto de patrones para la arquitectura.En su libro The Timeless Way of Building (1979) describe algo llamado “the quality without a name”:

Los sistemas bien diseñados poseen una esencia cualitativa que equilibra sus fuerzas internas.

Franco Guidi Polanco 8

Definición de patrón

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without

ever doing it the same way twice”

- Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King, and Shlomo Angel.

“A Pattern Language”Oxford University Press, NY, 1977.

Page 3: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 9

Utilidad de los patrones

Representan soluciones a problemáticas recurrentes en un dominio de trabajo.Son útiles porque:

Capturan y transmiten la experiencia de expertosEvitan la pérdida de tiempo en la búsqueda de soluciones ya existentesDefinen un “lenguaje” que simplifica la comunicación entre los desarrolladores.

Franco Guidi Polanco 10

Descripción de un patrón

Un patrón tiene al menos cuatro elementos:

Nombre: Una palabra o frase simple que describe el patrón

Problema: una descripción del problema

Contexto: cuándo se presenta el problema

Solución: los componentes del diseño, sus interrelaciones y responsabilidades (no implementación)

Franco Guidi Polanco 11

Patrones en ingeniería del software

Los ingenieros de software han estudiado el trabajo de Christopher Alexander, y han aplicado sus métodos para encontrar patrones en sistemas de software:

1987: Cunningham & Beck aplicaron las ideas de Alexander para desarrollar cinco patrones para diseñar interfaces de usuario1994: Gamma, Helm, Vlissides & Johnson (conocidos como TheGang of Four -GoF) publican el libro “Design Patterns – Elements of Reusable Object-Oriented Software”

Estos patrones aparecen en arquitecturas de alto nivel y en diseño detallado.

Los patrones de son, en consecuencia, una forma de documentar experiencias en el desarrollo de software.

Franco Guidi Polanco 12

Tipos de patrones en ingeniería de software

Patrones de diseño: para el desarrollo de software (mayoritariamente orientado a objetos)

Patrones de análisis: para definir modelos de análisis recurrentes y reutilizables

Patrones organizacionales: para estructurar organizaciones y proyectos

Patrones de procesos: para definir procesos de desarrollo de software

Page 4: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 13

Patrones y reutilización

Permiten reutilización de diseño

Son independientes del lenguaje de programación, no se requiere mantener librerías de código.

Permiten desarrollar código más fácilmente comprensible (luego, simplifican la mantención del software)

Facilitan la extensibilidad del software

Apoyan el diseño coordinado

Franco Guidi Polanco 14

Calidad de software

“All well-structured object-oriented architectures are full of patterns. Indeed, one of the ways that I measure the quality of an object-oriented system is to judge whether or not its developers

have paid careful attention to the common collaborations among its objects. Focusing on such mechanisms during system’s

development can yield an architecture that is smaller, simpler, and far more understandable than if these patterns are ignored.”

- Grady BoochForeword

“Design Patterns - Elements of Reusable Object-Oriented Software”, E. Gamma et al

Franco Guidi Polanco 15

Para convertirse en (*)…

…Campeón de ajedrez, se debe:

Aprender las reglasNombres, movimientos posibles de piezas, etc.

Aprender los principiosValor relativo de las piezas, valor estratégico de algunas zonas del tablero

Estudiar partidas de campeonesSecuencias de movimientos que deben ser entendidas (patrones), aprendidas y aplicadas

…Diseñador de software, se debe:

Aprender las reglasAlgoritmos, estructuras de datos, lenguajes de programación, etc.

Aprender los principiosProgramación estructurada, programación Orientada a Objetos.

Estudiar los patrones famososLos patrones deben ser entendidos, memorizados y aplicadosHay un centenar de patrones…

* Tomado de: Gambosi, Giorgio. “Corso di Architettura dei Sistemi Software”Università degli Studi di Roma “Tor Vergata”

Franco Guidi Polanco 16

Patrones GoF

Gamma E., Helm R. , Johnson R., Vlissides J., “Design Patterns: Elements of Reusable Object Oriented Software”, Addison Wesley, 1995.Catálogo de 23 patrones de diseño:

De CreaciónDe ComportamientoEstructurales

Page 5: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 17

Patrones GoF: De Creación

Asegura que una clase tenga sólo una instancia y provee un modo de acceso a ella.

Singleton

Especifica el tipo de objeto a crear por medio de una instancia prototipo, y crea nuevos objetos copiando este prototipo.

Prototype

Define una interfaz para crear un objeto, pero permite definir a las subclases qué clase instanciar.

Factory Method

Define una interfaz para la creación de familias de objetos relacionadas, sin especificar las clases específicas de estos objetos.

Abstract Factory

Separa la construcción de un objeto complejo de su repreentación, de forma tal de utilizar el mismo proceso de cosntrucción para obtener diferentes representaciones.

Builder

DescripciónPatrón de diseño

Franco Guidi Polanco 18

Patrones GoF: Estructurales

Provee una interfaz única y simplificada para interactuar en forma más fácil con un subsistema.

Facade

Implementa un objeto intermedio que controla accesos a un objeto específico. Proxy

Provee el uso compartido de objetos de granulardad fina, para mejorar la eficiencia en su empleo.

Flyweight

Agrega nuevas responsabilidades en forma ínámica a un objeto; se presenta como alternativa a la hererencia para la extensión de funcionalidades.

Decorator

Especifica una interfaz homogénea para tratar objetos simples y composiciones recursivas.

Composite

Desacopla una abstracción de su implementación, de modo que puedan variar en forma independiente.

Bridge

Convierte la interfaz de una clase en otra, permitiendo que ésta pueda ser utilizada.Adapter

DescripciónPatrón de Diseño

Franco Guidi Polanco 19

Patrones GoF: De Comportamiento

Define un objeto que encapsula la forma en que un conjunto de objetos interactua, de modo tal de favorecer el desacoplamiento entre ellos.

Mediator

Captura y externaliza el estado interno de un objeto, sin violar la encapsulación, de modo tal de poder reestablecer su estado más adelante.

Memento

Provee un modo de acceso secuencial a los elementos de un objeto agregado, sin exponer la implementación interna de este último.

Iterator

Dado un lenguaje, define una representación para su gramática, y un mecanismo de interpretación que utilice tal representación para interpretar sentencias en tal lenguaje.

Interpreter

Encapsula una solicitud en un objeto, permitiendo parametrizar clientes con diferentes solicitudes, poner estas solicitudes en cola, y soportar operaciones revertibles.

Command

Evita el acoplamiento entre quien envía una solicitud y quien la recibe, permitiendo que otros objetos manejen dicha solicitud.

Chain of Responsability

DescripciónPatrón de Diseño

Franco Guidi Polanco 20

Patrones GoF: De Comportamiento

Representa una opedración a ejecutar sobre una dertermina estructura de objetos.

Visitor

Define el esqueleto de un algoritmo en una operación , dejando ciertos pasos para una implementación posterior.

Template Methods

Define una familia de algoritmos, encapsula cada uno y los vuelve, desdee la perspectiva de quien los utiliza, intercambiables entre si.

Strategy

Permite a un objeto cambiar de comportamiento de acuerdo con su estado interno. El objeto parece cambiar de clase.

State

Define una dependencia 1 a N entre objetos, de modo que si uno cambia de estado los otros sean inmediatamente informados. Observer

DescripciónPatrón de Diseño

Page 6: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Adapter

Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

(Patrón de GoF)

Franco Guidi Polanco 22

Ejemplo

Se desea desarrollar una palicación que trabaja con figuras geométricas. Las figuras deberán implementar una interfaz particular (Polygon) Se tiene a disposición una antigua clase (Rectangle) que provee las operaciones esperadas, pero mediante una interfaz distinta, no modificable. Problema: ¿cómo es posible reutilizar la clase existente para que adhiera a la nueva interfaz, pero sin modificarla?

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

Franco Guidi Polanco 23

El patrón de diseño Adapter

Nombre: Adapter

Sinopsis: El patrón Adapter convierte la interfaz de una clase en la interfaz que un cliente espera.

Nota: Este patrón provee dos versiones: ClassAdpter y Object Adapter.

Franco Guidi Polanco 24

Modelo: Class Adapter

Participantes:

Client: accede al objeto adaptado mediante una interfaz predefinida (TargetInterface).

TargetInterface: interfaz que el cliente espera.

Adaptee: objeto que posee una determinada interfaz que debe ser adaptada.

Adapter :convierte la interfaz del objeto por adaptar (Adaptee) a la interfaz esperada por el cliente.

+ request()

<<stereotype>>Adapter

+ request()

<<stereotype>>Adapter

+request()

<<stereotype>>TargetInterface

+request()

<<stereotype>>TargetInterface

<<stereotype>>Client

+ specificRequest()

<<stereotype>>Adaptee

+ specificRequest()

<<stereotype>>Adaptee

request() {specificRequest();

}

Page 7: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 25

Modelo del problema: Class Adapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

ClassAdapterExample

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

Participantes:

Client: ClassAdapterExampleaccede al objeto adaptado mediante la interfaz Polygon.

TargetInterface: Polygon es interfaz que el ClassAdapterExample espera.

Adaptee: Rectangle posee una una interfaz que debe ser adaptada a Polygon.

Adapter : RectangleClassAdapterconvierte la interfaz de Rectangle a la interfaz Polygon.

Franco Guidi Polanco 26

Implementación: Class Adapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

ClassAdapterExample

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

public interface Polygon {

public void define( float x0, float y0, float x1, float y1, String color );public float[] getCoordinates() ;public float getSurface();public void setId( String id );public String getId( );public String getColor();

}

Franco Guidi Polanco 27

Implementación: Class Adapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

ClassAdapterExample

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

public class Rectangle {private float x0, y0, height, width; private String color;

public void setShape(float x, float y, float a, float l, String c) {x0 = x; y0 = y;height = a; width = l; color = c;

}

public float getArea() { return x0 * y0; }

public float getOriginX() { return x0; }

public float getOriginY() { return y0; }

public float getOppositeCornerX() { return x0 + height; }

public float getOppositeCornerY() { return y0 + width; }

public String getColor() { return color; }

}

Franco Guidi Polanco 28

Implementación: Class Adapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

ClassAdapterExample

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

public class RectangleClassAdapter extends Rectangle implements Polygon{

private String name = "NO NAME";public void define( float x0, float y0, float x1, float y1,

String color ) {float a = x1 - x0;float l = y1 - y0;setShape( x0, y0, a, l, color );

}

public float getSurface() { return getArea(); }

public float[] getCoordinates() { float aux[] = new float[4];aux[0] = getOriginX();aux[1] = getOriginY();aux[2] = getOppositeCornerX();aux[3] = getOppositeCornerY();return aux;

}

public void setId( String id ) { name = id; }

public String getId( ) { return name; }

}

Page 8: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 29

Implementación: Class Adapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String

RectangleClassAdapter

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

+define(x0:float, y0:float , x1:float , y1:float, color:String )

+getCoordinates():float[] +getSurface():float+setId( String id )+getId( ):String+getColor():String;

<<interface>>Polygon

ClassAdapterExample

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

+setShape(x:float, y:float, wide:float, height:float, color:String)

+ getArea():float+ getOriginX() :float+ getOriginY() :float+ getOppositeCornerX() :float+ getOppositeCornerY():float+ getColor() : String

Rectangle

public class ClassAdapterExample {public static void main( String[] arg ) {

Polygon block = new RectangleClassAdapter();block.setId( "Demo" );block.define( 3 , 4 , 10, 20, "RED" );System.out.println( "The area of "+ block.getId() + " is "+

block.getSurface() + ", and it's " +block.getColor() );

}}

Franco Guidi Polanco 30

Modelo: Object Adapter

Tarea: buscar la explicación de este modelo y aplicarla al ejemplo.

Composite

Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

(Patrón de GoF)

Franco Guidi Polanco 32

Ejemplo

Una distribuidora de computadores mantiene equipos armados listos para la venta y repuestos. Para efectos de manejo de inventario, ellos se consideran unidades indivisibles (ej. monitor, teclado) o compuestas por otros elementos (ej. main system, computador).

Computer

Main System Monitor Keyboard

Processor Hard Disk RAM

Page 9: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 33

Ejemplo

Se desea construir un sistema que permita mantener el inventario de productos, tratando de forma similar aquellos simples y aquelloscompuestos.Todos los objetos proveen un método para describirse. La descripciones de los objetos compuestos es función de las descripciones de suscomponentes.

Descripción de un objeto “simple”:Component: LCD Monitor

Descripción del objeto compuesto “main system”:

Component: Main SystemComposed by:{Component: Pentium III ProcessorComponent: 256 KB RAMComponent: 40 Gb Hard Disk}

Descripción del objeto compuesto “Computer”:Component: ComputerComposed by:{Component: LCD MonitorComponent: Italian KeyboardComponent: Main SystemComposed by:{Component: Pentium III ProcessorComponent: 256 KB RAMComponent: 40 Gb Hard Disk}}

Franco Guidi Polanco 34

Aproximación

Una aproximación sería la siguiente:

Ítem

Processor

El método describe() es implementado por cada subclase

Hard Disk

describe() describe() describe()

RAM

describe()

Main System

describe()

Computer

describe()

¿Problemas?

Franco Guidi Polanco 35

El patrón Composite

Nombre: Composite

Sinopsis: El patrón composite permite representar jerarquías de objetos del tipo todo-parte. Estas jerarquías permiten dar el mismo tratamiento a objetos simples y compuestos.

Franco Guidi Polanco 36

Modelo

Participantes:

Component: declara la interfaz que implementan todos los objetos e implementa el comportamiento común de todos ellos

Leaf: representa a los objetos elementales de la composición.

Composite: almacena a los objetos componentes y define el comportamiento de objetos compuestos.

Client: manipula los objetos a través de la interfaz Component

<<stereotype>>Client

<<stereotype>>Component

{abstract}

+add(Component) +remove(Component):boolean+getChild(int):Component+operation()

children

*

<<stereotype>>Leaf

+operation()

<<stereotype>>Composite

+add(Component) +remove(Component):boolean+getChild(int):Component+operation()

operation() {for all g in children {

g.operation();}

}

Page 10: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 37

Modelo del problema

Participantes:

Component: Componentdeclara la interfaz que implementan todos los objetos e implementa comportamiento común de todos ellos.

Leaf: SinglePart representa a los objetos elementales de la composición.

Composite: CompoundPartalmacena a los objetos componentes. Implementa describe() invocando a describe() de sus componentes.

Client: Mainmanipula los objetos a través de la interfaz de Component

Main

SinglePart

+ describe() : void

Component

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

CompoundPart

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

0..*

-theChildren

0..*

Franco Guidi Polanco 38

SinglePart

+ describe() : void

Component

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

CompoundPart

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

0..*

-theChildren

0..*

Implementación

Main

public abstract class Component {

public String name;

public Component(String aName){name = aName;

}public abstract void describe();public void add(Component c) throws SinglePartException {

if (this instanceof SinglePart)throw new SinglePartException( );

}public void remove(Component c) throws SinglePartException{

if (this instanceof SinglePart)throw new SinglePartException( );

}public Component getChild(int n){

return null;}

}

Franco Guidi Polanco 39

SinglePart

+ describe() : void

Component

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

CompoundPart

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

0..*

-theChildren

0..*

Implementación (cont.)

Main

public class SinglePart extends Component {

public SinglePart(String aName) {super(aName);

}

public void describe(){System.out.println( "Component: " + name );

}}

Franco Guidi Polanco 40

SinglePart

+ describe() : void

Component

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

CompoundPart

+ add(component : Component) : void+ remove(component : Component) : boolean+ getChild(index : int) : Component+ describe() : void

0..*

-theChildren

0..*

Implementación (cont.)

Main

public class CompoundPart extends Component {

private Vector children ;

public CompoundPart(String aName) {super(aName);children = new Vector();

}public void describe(){

System.out.println("Component: " + name);System.out.println("Composed by:");System.out.println("{");int vLength = children.size();for( int i=0; i< vLength ; i ++ ) {

Component c = (Component) children.get( i );c.describe();

}System.out.println("}");

}public void add(Component c) throws SinglePartException {

children.addElement(c);}public void remove(Component c) throws SinglePartException{

children.removeElement(c);}public Component getChild(int n) {

return (Component)children.elementAt(n);}

}

Page 11: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 41

Implementación (cont.)

Cliente

// Crea hojasComponent monitor = new SinglePart("LCD Monitor");Component keyboard = new SinglePart(“English Keyboard");Component processor = new SinglePart("Pentium III Processor");Component ram = new SinglePart("256 KB RAM");Component hardDisk = new SinglePart("40 Gb Hard Disk");

// un composite con 3 hojasComponent mainSystem = new CompoundPart( "Main System" );mainSystem.add( processor );mainSystem.add( ram );mainSystem.add( hardDisk );

// un composite compuesto por otro composite y por una hojaComponent computer = new CompoundPart("Computer");computer.add( monitor );computer.add( keyboard );computer.add( mainSystem );

System.out.println( "** Describe el componente 'monitor'" );monitor.describe();System.out.println( "** Describe el componente 'main system'" );mainSystem.describe();System.out.println( "** Describe el componente 'computer'" );computer.describe(); Franco Guidi Polanco 42

Implementación (cont.)** Describe el componente 'monitor'Component: LCD Monitor** Describe el componente 'main system'Component: Main SystemComposed by:{Component: Pentium III ProcessorComponent: 256 KB RAMComponent: 40 Gb Hard Disk}** Describe el componente 'computer'Component: ComputerComposed by:{Component: LCD MonitorComponent: Italian KeyboardComponent: Main SystemComposed by:{Component: Pentium III ProcessorComponent: 256 KB RAMComponent: 40 Gb Hard Disk}}

Factory Method(Patrón de GoF)

Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

Franco Guidi Polanco 44

Ejemplo

Se desea desarrollar un framework para la manipulación de grafos(mapas, circuitos, etc.). Se han identificado al menos dos clases abstractas: la clase Elemento (que representa cualquier tipo de objeto a posicionar en el grafo), y la clase Instrumento, que provee operaciones para manipular elementos.La implementación de aplicaciones a partir de este framework requiere la extensión de las clases Elemento e Instrumento.

Place:

Lausanne(Switzerland)

Place:

Evian(France)

Connector:

Lac Léman

New Place New Conn.Tools:

Inscripción

New Entity New Association.Tools:

Alumno Curso

Aplicación cartográfica Herramienta CASE

Page 12: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 45

Ejemplo (cont.)

El framework “sabe” cuándo debe crear un nuevo elemento, pero no “sabe” qué tipo de elemento crear.

Franco Guidi Polanco 46

El patrón Factory Method

Nombre: Factory Method

Sinopsis: conociendo el momento en el cual se debe crear un objeto, permite delegar a una clase (posiblemente una subclase del sistema desarrollado) la creación del mismo.

Este patrón encapsula la lógica de instanciación de un objeto en una clase específica.

Franco Guidi Polanco 47

#factoryMethod(): Product +anOperation()

#factoryMethod(): Product

creates<<instantiates>>

anOperation{…product=factoryMethod();…

}

<<stereotype>>Product

<<stereotype>>Creator

<<stereotype>>ConcreteCreator

<<stereotype>>ConcreteProduct

Modelo

Participantes:

Product: declara la interfaz de los objetos a crear por el factory method.

ConcreteProduct: implementa la interfaz Product.

Creator: declara el factorymethod, que retorna un objeto del tipo Product. Puede implementar un comportamiento defaultpara el factory method.

ConcreteCreator: Sobreescribe o implementa el factory method para retornar una instancia de ConcreteProduct.

Franco Guidi Polanco 48

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

Modelo del problema

Participantes:

Product: Element - interfaz de los objetos graficables.

ConcreteProduct: Place y Connector – objetos concretos a graficar.

Creator: ElementHandler -determina genéricamente la instanciación de un objeto. Declara el factory method.

ConcreteCreator: PlaceHandler y ConnectorHandler -implementan el factory methodmediante el retorno de un objeto de la clase Place o Connector, respectivamente.

Page 13: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 49

Implementación

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

public interface Element {

public abstract void setLabel( String id );

public abstract String getPaintingData();

}

Franco Guidi Polanco 50

Implementación (cont.)

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

public abstract class ElementHandler {

public Element createElement( ) throws IOException {BufferedReader reader = new BufferedReader( new

InputStreamReader( System.in) );System.out.println( "Enter a label for the element: ");String label = reader.readLine();Element element = newElement( );element.setLabel( label );return element;

}

public abstract Element newElement();

public void paintElement(Element element) {System.out.println( element.getPaintingData() );

}}

Franco Guidi Polanco 51

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

Implementación (cont.)

public class Place implements Element {

private String placeLabel;

public void setLabel( String label ) {placeLabel = label;

}

public String getPaintingData() {return "city: "+ placeLabel;

}

}

Franco Guidi Polanco 52

Implementación (cont.)

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

public class Connector implements Element {

private String connectorLabel;Place place1, place2;

public void setLabel( String label ) {connectorLabel = label;

}

public void setPlacesConnected(Placeorigin, Place destination ) {

place1 = origin;place2 = destination;

}

public String getPaintingData() {return connectorLabel + " [from " +

place1.getPaintingData() + " to " +place2.getPaintingData() + "]";

}

}

Page 14: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 53

Implementación (cont.)

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

public class PlaceHandler extends ElementHandler {

public Element newElement() {return new Place();

}

}

Franco Guidi Polanco 54

Implementación (cont.)

creates

#newElement(): MapElement +createElement(): MapElement+paintElement()

ElementHandler

#newElement(): MapElement

PlaceHandler

<<interface>>Element

+setLabel()+getPaintingData(): String

Place

+setLabel()+getPaintingData(): String

#newElement(): MapElement+connect( conn: Connector,

origin: Place, destination: Place )

ConnectorHandler

createsConnector

+setLabel()+getPaintingData():String

public class ConnectorHandler extends ElementHandler {

public Element newElement() {return new Connector();

}

public void connect(Connector conn, Place origin, Place destination) {

conn.setPlacesConnected( origin, destination );}

}

Franco Guidi Polanco 55

Implementación (cont.)

Main// Crea las herramientas para manejar elementos

ConnectorHandler cTool = new ConnectorHandler();PlaceHandler pTool = new PlaceHandler();

// VariablesPlace startPoint, endPoint;Connector route;

// Crea dos lugares y un conectorSystem.out.println( "1st. place creation" );startPoint = (Place) pTool.createElement();System.out.println( "2nd. place creation" );endPoint = (Place) pTool.createElement();System.out.println( "Connector creation" );route = (Connector) cTool.createElement();

// Conecta los lugares con el conectorcTool.connect( route, startPoint , endPoint );

// Dibuja el grafopTool.paintElement( startPoint );pTool.paintElement( endPoint );cTool.paintElement( route );

Franco Guidi Polanco 56

Implementación (cont.)

Ejecución:

1st. place creationEnter a label for the element:Evian

2nd. place creationEnter a label for the element:Lausanne

Connector creationEnter a label for the element:Lac Léman

city: Eviancity: LausanneLac Léman [from city: Evian to city: Lausanne]

Page 15: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 57

Una variación del Factory method: el StaticFactory pattern

Propone adoptar la “encapsulación de reglas de instanciación”, utilizando métodos estáticos. De esta forma, la obtención de referencias a objetos del tipo requerido se logra invocando el método estático correspondiente.

Su implementación requiere:La declaración del constructor de la clase como “privado” La implementación de uno o más métodos estáticos que se encarguen de retornar una instancia del objeto requerido.

Franco Guidi Polanco 58

Una variación del Factory method: el StaticFactory pattern

Ejemplo: Se desea implementar la clase Temperatura. Un objeto de esta clase mantiene un valor de temperatura que es determinado al momento de la instanciación. La clase debe manejar temperaturas tanto en grados Celsius como en grados Fahrenheit.¿Cómo se logra asignar el valor al momento de la instanciación?

public class Temperatura{double tempC;public Temperatura(double temp){

// setea la temperatura }public double getF(){…}public double getC(){…}

}

¿Cómo hacer para instanciarel objetoa partir de temperaturas en ºF o en ºC?

Franco Guidi Polanco 59

Una variación del Factory method: el StaticFactory pattern (cont.)

Solución:public class Temperatura{

double tempC;private Temperatura(double t){

tempC = t;}public static Temperatura newTempFromC(double t){

return new Temperatura( t );}public static Temperatura newTempFromF(double t){

return new Temperatura( (t-32)*5/9 );}public double getC(){

return tempC;}public double getF(){

return 9*tempC/5+32;}

}

Franco Guidi Polanco 60

Una variación del Factory method: el StaticFactory pattern (cont.)

Ventajas del Static Factory pattern:Los static factory methods pueden tener nombres, los constructores no. Al tener nombres se evitan conflictos entre constructores con parámetros similaresNo es necesario que siempre se deba crear una instancia nueva (por ejemplo, ver pattern Singleton)Puede retornar objetos de subclases.

Desventajas:Una static factory no puede tener subclases (el constructor es privado)Un satic factory method puede ser fácilmente confundido con cualquier otro método (se requiere adoptar una convención de nombres)

Page 16: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Strategy

(Patrón de GoF)

Franco Guidi Polanco 62

Ejemplo

En el desarrollo de un software matemático se ha definido una clase que manejará vectores. Entre los métodos de esta clase existe uno que permite la impresión por pantalla. Tal impresión puede ser de distintas formas:

{ 11, -7, 3, … } (por ej. llamado standard format)arr[0]=11 arr[1]=-7 arr[2]=3 … (por ej. llamada math format)

Es válido pensar que tales formatos podrían ser sustituidos por otrosPor lo tanto es conveniente encontrar una forma de aislar el código responsable del formateo e impresión de los datos.

Franco Guidi Polanco 63

El patrón Strategy

Nombre: Strategy

Sinopsis: define una familia de algoritmos, encapsula cada uno y los hace intercambiables. De esta forma los algoritmos pueden variar independientemente de los clientes que los utilizan.

Este patrón encapsula la lógica de operación de un determinado proceso, utilizando una clase específica.

Franco Guidi Polanco 64

<<stereotype>>Context

+contextInterface()

<<stereotype>>Strategy{interface}

+algorithmInterface()

<<stereotype>>ConcreteStrategy

+algorithmInterface()

strategy

1

Modelo

Participantes:

Strategy: declara una interfaz común para todos los algoritmos soportados.

ConcreteStrategy: implementa los algoritmos, utilizado la interfaz Strategy.

Context: es configurado con una ConcreteStrategy, y mantiene una referencia al Strategy object. Puede definir una interfaz que permita a la Strategyacceder a sus datos.

Page 17: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 65

Modelo del problema

ArrayDisplayFormat{interface}

+printData( array: int[ ] )

StandardFormat

+printData(array: int[ ] )

format

1

setDisplayFormat(ArrayDisplayFormat adf ) {format =adf;

}

MyArray

- array : int[ ]

+setValue(pos:int, value:int ): void+getValue( int pos):int +setDisplayFormat (adf: ArrayDisplayFormat)+display()

display() {format.printData(array);

}MathFormat

+printData( array: int[ ] )

Participantes:

Strategy:ArrayDisplayFormatDeclara una interfaz común para todos los algoritmos de impresión.

ConcreteStrategy: SandardFormat y MathFormatImplementan los algoritmos de impresión, utilizado la interfaz ArrayDisplayFormat.

Context: MyArrayEs configurado con un StandardFormat o un MathFormat, para lograr la impresión adecuada.

Franco Guidi Polanco 66

Implementación

ArrayDisplayFormat{interface}

+printData( array: int[ ] )

StandardFormat

+printData( array: int[ ] )

format

1

setDisplayFormat(ArrayDisplayFormat adf ) {format =adf;

}

MyArray

- array : int[ ]

+setValue(pos:int, value:int ): void+getValue( int pos):int +setDisplayFormat (adf: ArrayDisplayFormat)+display()

display() {format.printData(array);

}MathFormat

+printData( array: int[ ] )

public class MyArray {private int[] array;private int size;ArrayDisplayFormat format;public MyArray( int size ) {

array = new int[ size ];}public void setValue( int pos, int value ) {

array[pos] = value;}public int getValue( int pos ) {

return array[pos];}public int getLength( int pos ) {

return array.length;}public void setDisplayFormat( ArrayDisplayFormat adf ) {

format = adf;}public void display() {

format.printData( array );}

}

Franco Guidi Polanco 67

Implementación (cont.)

ArrayDisplayFormat{interface}

+printData( array: int[ ] )

StandardFormat

+printData( array: int[ ] )

format

1

setDisplayFormat(ArrayDisplayFormat adf ) {format =adf;

}

MyArray

- array : int[ ]

+setValue(pos:int, value:int ): void+getValue( int pos):int +setDisplayFormat (adf: ArrayDisplayFormat)+display()

display() {format.printData(array);

}MathFormat

+printData( array: int[ ] )

public interface ArrayDisplayFormat {

public void printData( int[] arr );

}

Franco Guidi Polanco 68

Implementación (cont.)

ArrayDisplayFormat{interface}

+printData( array: int[ ] )

StandardFormat

+printData( array: int[ ] )

format

1

setDisplayFormat(ArrayDisplayFormat adf ) {format =adf;

}

MyArray

- array : int[ ]

+setValue(pos:int, value:int ): void+getValue( int pos):int +setDisplayFormat (adf: ArrayDisplayFormat)+display()

display() {format.printData(array);

}MathFormat

+printData( array: int[ ] )

public class StandardFormatimplements ArrayDisplayFormat {

public void printData( int[] arr ) {System.out.print( "{ " );for(int i=0; i < arr.length-1 ; i++ )

System.out.print( arr[i] + ", " );System.out.println( arr[arr.length-1] + " }" );

}}

Page 18: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 69

Implementación (cont.)

ArrayDisplayFormat{interface}

+printData( array: int[ ] )

StandardFormat

+printData( array: int[ ] )

format

1

setDisplayFormat(ArrayDisplayFormat adf ) {format =adf;

}

MyArray

- array : int[ ]

+setValue(pos:int, value:int ): void+getValue( int pos):int +setDisplayFormat (adf: ArrayDisplayFormat)+display()

display() {format.printData(array);

}MathFormat

+printData( array: int[ ] )

public class MathFormat implements ArrayDisplayFormat {

public void printData( int[] arr ) {for(int i=0; i < arr.length ; i++ )

System.out.println( "Arr[ " + i + " ] = " + arr[i] );}

}

Franco Guidi Polanco 70

Implementación (cont.)

Ejemplo de aplicación:MyArray m = new MyArray( 10 );m.setValue( 1 , 6 );m.setValue( 0 , 8 );m.setValue( 4 , 1 );m.setValue( 9 , 7 );System.out.println("This is the array in 'standard' format");m.setDisplayFormat( new StandardFormat() );m.display();System.out.println("This is the array in 'math' format:");m.setDisplayFormat( new MathFormat() );m.display();

This is the array in 'standard' format :{ 8, 6, 0, 0, 1, 0, 0, 0, 0, 7 }

This is the array in 'math' format:Arr[ 0 ] = 8Arr[ 1 ] = 6Arr[ 2 ] = 0Arr[ 3 ] = 0Arr[ 4 ] = 1Arr[ 5 ] = 0Arr[ 6 ] = 0Arr[ 7 ] = 0Arr[ 8 ] = 0Arr[ 9 ] = 7Output:

Decorator(Patrón de GoF)

Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

Franco Guidi Polanco 72

Ejemplo

Suponga un modelo OO que representa Empleados (Employee) de una empresa. Entre los empleados existen, por ejemplo, Ingenieros (Engineer) que implementan operaciones definidas para los Empleados de acuerdo con características propias.

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

El método whoIs() imprime una descripción del empleadoLa descripción depende de lasresponsabilidades del objeto.

Page 19: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 73

Ejemplo

El sistema debe manejar empleados con distintas responsabilidades:Un empleado puede ser un IngenieroUn empleado puede ser Jefe AdministrativoUn empleado puede ser en Jefe de Proyecto.

Las responsabilidades no son excluyentes entre si

Employee{interface}

Engineer

AdministrativeManager ProjectManager

Administrative&ProjectManager

Administrative&2ProjectsManager

El método whoIs() es diferentecada tipo de empleado.

Franco Guidi Polanco 74

Ejemplo

Los cambios de tipología de algunos empleados involucran la modificación de responsabilidades definidas para los objetos, alterando las existentes, o agregando nuevas.Estas modificaciones ocurren dinámicamente durante el ciclo de vida de un objeto.

Franco Guidi Polanco 75

Resultado esperado

Se busca una forma para agregar y remover dinámicamente nuevas responsabilidades a un empleado.

Who are you?I am William Gateway, and I am with the Programming Department.

Who are you now?I am a boss. I am William Gateway, and I am with the Programming Department.

Who are you now?I am a boss. I am William Gateway, and I am with the Programming Department.I am the Manager of the Project: D.O.S.- Doors Operating System

Who are you now?I am a boss. I am William Gateway, and I am with the Programming Department.I am the Manager of the Project: D.O.S.- Doors Operating SystemI am the Manager of the Project: EveryoneLoggedToInternet Explorer

El empleado asume una dirección administrativa:

El empleado/administrador asume una jefatura de proyecto:

El empleado/administrador/jefe proyecto asume otra jefatura de proyecto:

Franco Guidi Polanco 76

El patrón Decorator

Nombre: Decorator

Sinopsis: El patrón Decorator extiende dinámicamente la funcionalidad de un objeto en forma transparente para sus “clientes”. Provee una forma de alternativa a la generación de subclases, a fin de extender funcionalidades.

Page 20: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 77

Modelo

Participantes:

Component: especifica lainterfaz de los objetos a los cuales se les puede modificar sus funcionalidades dinámicamente.

ConcreteComponent: implementa el objeto al cual se le pueden modificar susfuncionalidades dinámicamente.

Decorator: posee una referenciaal objeto Component y especificauna interfaz concordante con la interfaz de Component.

ConcreteDecorator: agrega nuevas responsabilidades alComponent.

<<stereotype>>Component

+operation()

<<stereotype>>Component

+operation()

<<stereotype>>ConcreteComponent

+operation()

<<stereotype>>ConcreteComponent

+operation()

<<stereotype>>Decorator

+operation()

<<stereotype>>Decorator

+operation()

operation{component.operation();

}

component

<<stereotype>>ConcreteDecorator

+operation()-addedBehaviour()

-addedState

<<stereotype>>ConcreteDecorator

+operation()-addedBehaviour()

-addedState

Franco Guidi Polanco 78

Modelo del problema

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

Participantes:Component: EmployeeEspecifica la interfaz de los objetos a los cuales se les puede modificar sus funcionalidades dinámicamente.

ConcreteComponent: EngineerImplementa el objeto al cual se le puedenmodificar sus funcionalidadesdinámicamente.

Decorator: ResponsibleWorkerPosee una referencia al objeto Employee y especifica una interfaz concordante suinterfaz.

ConcreteDecorator: AdministrativeManager y ProjectManagerAgregan nuevas responsabilidades al Engineer (Employee).

Franco Guidi Polanco 79

Implementación

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

public interface Employee {public String getName();public String getOffice();public void whoIs();

}

Franco Guidi Polanco 80

Implementación (cont.)

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

public class Engineer implements Employee {private String name, office;public Engineer( String nam, String off ) {

name = nam;office = off;

}public String getName() {

return name ;}public String getOffice() {

return office ;}public void whoIs() {

System.out.println( "I am " + getName() + ", and I am with the "

+ getOffice() +".");};

}

Page 21: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 81

Implementación (cont.)

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

abstract class ResponsibleWorkerimplements Employee {

protected Employee responsible;public ResponsibleWorker(Employee employee) {

responsible = employee;}public String getName() {

return responsible.getName();}public String getOffice() {

return responsible.getOffice();}public void whoIs() {

responsible.whoIs();}

}

Franco Guidi Polanco 82

Implementación (cont.)

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

public class AdministrativeManagerextends ResponsibleWorker {

public AdministrativeManager( Employee empl ) {super( empl );

}public void whoIs() {

sayIamBoss();super.whoIs();

}private void sayIamBoss(){

System.out.print( "I am a boss. " );}

}

Franco Guidi Polanco 83

Implementación (cont.)

Employee{interface}

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

Engineer

+getName(): String+getOffice(): String+whoIs()

ResponsibleWorker

+getName(): String+getOffice(): String+whoIs()

component

AdministrativeManger

+whoIs()-sayIamBoss()

AdministrativeManger

+whoIs()-sayIamBoss()

ProjectManger

+whoIs()

-project: String

ProjectManger

+whoIs()

-project: String

public class ProjectManager extends ResponsibleWorker {

private String project;public ProjectManager( Employee empl, String proj ) {

super( empl );project = proj;

}

public void whoIs() {super.whoIs();System.out.println( "I am the Manager of the Project:"

+ project );}

}

Franco Guidi Polanco 84

Diagramas de objetos

Un Empleado que a la vez es administrador:

:Engineer:AdministrativeManager

:ProjectManager

name=“William”dpt=“Programming”

:Engineer

name=“William”dpt=“Programming”

project=“DOORS”

Un Empleado que a la vez es jefe de un proyecto:

Page 22: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 85

Diagramas de objetos

Un Empleado que a la vez es administrador y jefe de proyecto:

:Engineer:AdministrativeManager

name=“William”dpt=“Programming”

:ProjectManager

project=“DOORS”

:Engineer:AdministrativeManager

name=“William”dpt=“Programming”

:ProjectManager

project=“DOORS”

:ProjectManager

project=“IE”

Un Empleado que a la vez es administrador y jefe de dos proyectos:

Franco Guidi Polanco 86

Implementación (cont.)

public class DecoratorExample1 {public static void main(String arg[]) {

Employee heWillBeFamous = new Engineer( "William Gateway", "Programming Department" );

System.out.println( "Who are you?");heWillBeFamous.whoIs();heWillBeFamous = new AdministrativeManager( heWillBeFamous );System.out.println( "Who are you now?");heWillBeFamous.whoIs();heWillBeFamous = new ProjectManager( heWillBeFamous,

"D.O.S.- Doors Operating System" );System.out.println( "Who are you now?");heWillBeFamous.whoIs();

heWillBeFamous = new ProjectManager( heWillBeFamous, "EveryoneLoggedToInternet Explorer" );

System.out.println( "Who are you now?");heWillBeFamous.whoIs();

}}

Cliente

Franco Guidi Polanco 87

Implementación (cont.)

public class DecoratorExample1 {public static void main(String arg[]) {

Employee heWillBeFamous = new Engineer( "William Gateway", "Programming Department" );

System.out.println( "Who are you?");heWillBeFamous.whoIs();heWillBeFamous = new AdministrativeManager( heWillBeFamous );System.out.println( "Who are you now?");heWillBeFamous.whoIs();heWillBeFamous = new ProjectManager( heWillBeFamous,

"D.O.S.- Doors Operating System" );System.out.println( "Who are you now?");heWillBeFamous.whoIs();

heWillBeFamous = new ProjectManager( heWillBeFamous, "EveryoneLoggedToInternet Explorer" );

System.out.println( "Who are you now?");heWillBeFamous.whoIs();

}}

Cliente

Who are you?I am William Gateway, and I am with the Programming Department.

Who are you?I am William Gateway, and I am with the Programming Department.

Franco Guidi Polanco 88

Implementación (cont.)

public class DecoratorExample1 {public static void main(String arg[]) {

Employee heWillBeFamous = new Engineer( "William Gateway", "Programming Department" );

System.out.println( "Who are you?");heWillBeFamous.whoIs();heWillBeFamous = new AdministrativeManager( heWillBeFamous );System.out.println( "Who are you now?");heWillBeFamous.whoIs();heWillBeFamous = new ProjectManager( heWillBeFamous,

"D.O.S.- Doors Operating System" );System.out.println( "Who are you now?");heWillBeFamous.whoIs();

heWillBeFamous = new ProjectManager( heWillBeFamous, "EveryoneLoggedToInternet Explorer" );

System.out.println( "Who are you now?");heWillBeFamous.whoIs();

}}

Cliente

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.

Page 23: Craig Larman, “Applying UML and Patterns”eii.ucv.cl/pers/guidi/cursos/estructuras/pdf/SE-DesignPatterns.pdfLos ingenieros de software han estudiado el trabajo de Christopher Alexander,

Franco Guidi Polanco 89

Implementación (cont.)

public class DecoratorExample1 {public static void main(String arg[]) {

Employee heWillBeFamous = new Engineer( "William Gateway", "Programming Department" );

System.out.println( "Who are you?");heWillBeFamous.whoIs();heWillBeFamous = new AdministrativeManager( heWillBeFamous );System.out.println( "Who are you now?");heWillBeFamous.whoIs();heWillBeFamous = new ProjectManager( heWillBeFamous,

"D.O.S.- Doors Operating System" );System.out.println( "Who are you now?");heWillBeFamous.whoIs();

heWillBeFamous = new ProjectManager( heWillBeFamous, "EveryoneLoggedToInternet Explorer" );

System.out.println( "Who are you now?");heWillBeFamous.whoIs();

}}

Cliente

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.I am the Manager of the Project: D.O.S.- Doors Operating System.

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.I am the Manager of the Project: D.O.S.- Doors Operating System.

Franco Guidi Polanco 90

Implementación (cont.)

public class DecoratorExample1 {public static void main(String arg[]) {

Employee heWillBeFamous = new Engineer( "William Gateway", "Programming Department" );

System.out.println( "Who are you?");heWillBeFamous.whoIs();heWillBeFamous = new AdministrativeManager( heWillBeFamous );System.out.println( "Who are you now?");heWillBeFamous.whoIs();heWillBeFamous = new ProjectManager( heWillBeFamous,

"D.O.S.- Doors Operating System" );System.out.println( "Who are you now?");heWillBeFamous.whoIs();

heWillBeFamous = new ProjectManager( heWillBeFamous, "EveryoneLoggedToInternet Explorer" );

System.out.println( "Who are you now?");heWillBeFamous.whoIs();

}}

Cliente

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.I am the Manager of the Project: D.O.S.- Doors Operating SystemI am the Manager of the Project: EveryoneLoggedToInternet Explorer.

Who are you now?I am a boss. I am William Gateway, and I am with the ProgrammingDepartment.I am the Manager of the Project: D.O.S.- Doors Operating SystemI am the Manager of the Project: EveryoneLoggedToInternet Explorer.

Franco Guidi Polanco 91

¿Qué hemos logrado mediante el design pattern“decorator”?

Modificar dinámicamente las responsabilidades de un objeto.Generar clases a partir de otras, mediante un mecanismo alternativo a la herencia. Este mecanismo tiene las siguientes ventajas:

Puede genera una menor cantidad de clasesPermite generar clases que incorporan funcionalidades provistas por dos o más clases existentes (resuelve el problema de la herencia múltiple)

Franco Guidi Polanco 92

Ejercicio

Se está desarrollando un sistema de comunicaciones. Este sistema debe implementar la interfaz Transmisor, que posee el método transmitir, el cual recibe un String y lo transmite a un computador remoto. El sistema debe estar preparado para:

Transmitir textos sin modificacionesTransmitir textos comprimidosTransmitir textos encriptadosTransmitir textos encriptados y comprimidos

Desarrolle un diagrama de clases que permita resolver este problema.