Post on 13-Mar-2020
Design Patterns
Franco Guidi PolancoEscuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chilefguidi@ucv.cl
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….
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.
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
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
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
Adapter
Franco Guidi PolancoEscuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chilefguidi@ucv.cl
(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();
}
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; }
}
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, Chilefguidi@ucv.cl
(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
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();}
}
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);}
}
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, Chilefguidi@ucv.cl
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
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.
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() + "]";
}
}
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]
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)
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.
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] + " }" );
}}
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, Chilefguidi@ucv.cl
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.
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.
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() +".");};
}
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:
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.
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.