Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Gof Patrones de Diseño: Gang of Four
Gof Patrones de Diseño: Gang of Four
Patrones de diseño
*Gang of Four
GoF
Catálogo de patrones de diseño.
Década de los 90s, publicación del libro Design Patterns
escrito por el grupo Gang of Four (GoF) compuesto por
Erich Gamma, Richard Helm, Ralph Johnson y John
Vlisides, en el que se recogían 23 patrones de diseño
comunes.
Creacionales, estructurales y de comportamiento.
2
Motivación 1
3
Adapter
Problema:
Cómo manejar interfaces incompatibles, o
proveer una interfaz estable a componentes
similares con diferentes interfaces?
Comentemos…
Cada servicio externo tiene una interfaz diferente.
Cada sistema tiene un API que no podemos
modificar.
Podemos tener diferentes implementaciones para
un tipo de servicio.
4
Adapter (2)
Solución:
Convertir la interface original de un componente
en otra interface, a través de un objeto adaptador
intermedio.
5
«interface» Adapters use interfaces and
ITaxCalculatorAdapter polymorphism to add a level of
indirection to varying APIs in other
getTaxes( Sale ) : List of TaxLineItems components.
TaxMasterAdapter GoodAsGoldTaxPro
Adapter
«interface» «interface»
IAccountingAdapter ICredit AuthorizationService
Adapter
postReceivable( Credit Payment )
postSale( Sale ) requestApproval(Credit Payment,TerminalI D, MerchantID)
... ...
«interface»
IInventoryAdapter
SAPAccountingAdapter GreatNorthernAccountingAdapter
...
6
Uso del adapter
:Register : SAPAccountingAdapter
makePayment
...
SOAP over
HTTP
postSale( sale )
xxx «actor»
: SAPSystem
7
Adapter – Especialización de
GRASP
Adapter soporta protected variatios respecto al cambio de interfaces externas o paquetes
externos, a través del uso de indirection con un objeto que aplica interfaces y
polimorfismo.
GoF Design
Adapter Patterns
8
Factory
Llamado también Simple factory o Concrete factory.
Simplificación del GoF Abstract Factory
Motivación
Después de tener los Adaptadores, quién los crea? Cómo
determinar cual clase de adaptador crear? TaxMasterAdapter o
GoodAsGoldTaxProAdapter?
Problema:
Quién debería ser responsable de crear objetos
9
Factory (2)
Solución
Crear un objeto de fabricación pura llamado Factory que maneje
la creación.
Comentemos…
Si asignamos esa responsabilidad a un objeto del dominio,
entonces está haciendo más que la lógica pura de la aplicación.
(está respondiendo a aspectos de conectividad con
componentes de software externos)
Debemos diseñar siguiendo el principio de “separation of
concerns”
Por lo tanto creamos un objeto que maneje esta creación y que
mantenga una alta cohesión.
10
Factory
ServicesFactory note that the factory methods
return objects typed to an
accountingAdapter : IAccountingAdapter interface rather than a class, so
inventoryAdapter : IInventoryAdapter that the factory can return any
taxCalculatorAdapter : ITaxCalculatorAdapter implementation of the interface
getAccountingAdapter() : IAccountingAdapter
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapter
...
if ( taxCalculatorAdapter == null )
{
// a reflective or data-driven approach to finding the right class: read it from an
// external property
}
return taxCalculatorAdapter;
11
Ventajas
Separa la responsabilidad de creación
compleja en objetos de ayuda y cohesivos.
Esconde (potencialmente) la lógica de la
creación compleja de objetos.
Permite la introducción de estrategias de
administración de memoria que mejoran el
rendimiento.
Patrones relacionados:
Frecuentemente se usa con el patrón Singleton.
12
Singleton
Motivación
Del ejemplo anterior, entonces quién crea el ServiceFactory? O
cómo acceder a él?
Comentemos…
Solo una instancia del Factory es necesaria.
Los métodos del Factory pueden ser llamados de varios
lugares en el código, tantos como donde se use un adaptador
a un servicio externo.
Problema
Exactamente una instancia de una clase es
permitida (singleton). Los objetos necesitan un
punto de acceso único y global.
13
Singleton
Solución
Defina un método estático de la clase que retorne el singleton.
UML notation: this '1' can optionally be used to
indicate that only one instance will be created (a
singleton)
1
ServicesFactory
// static method
public static synchronized ServicesFactory getInstance()
{
if ( instance == null )
instance = new ServicesFactory()
return instance 14
}
Singleton
El desarrollador obtiene una visibilidad global a una única instancia
a través del método estático getInstance
public class Register {
public void initialize() { … do some work …
// accessing the singleton Factory via the getInstance
call accountingAdapter =
ServicesFactory.getInstance().getAccountingAdapter();
… do some work …
} // other methods… } // end of class
1
:Register
:ServicesFactory
initialize
aa = getAccountingAdapter
16
1
:Store
:ServicesFactory
create
create :Register
accountingAdapter =
getAccountingAdapter
create : SAPAccounting
Adapter
accountingAdapter:
:Register
SAPAccountingAdapter
makePayment
create(cashTendered) : Payment SOAP over
HTTP
postSale( sale )
xxx «actor»
: SAPSystem
17
Conclusión (2)
Ahora podemos decir:
18
Motivación 2
Se tiene una lógica de precios compleja
Descuentos por un día, por tipo de ciudadano.
La estrategia de precios puede variar, ej durante
un periodo puede ser descuento de 10% de todas
las ventas, luego puede ser de $10 si la venta es
mayor de $200, etc.
Cada estrategia puede ser llamada regla,
política o algoritmo.
Cómo diseñamos para variaciones en estos
algoritmos?
19
Strategy
Problema
Cómo diseñar para algoritmos o políticas variadas
pero relacionadas? Cómo diseñar con la habilidad
de cambiar estos algoritmos o políticas?
Solución
Definir cada algoritmo / política / estrategia en una
clase separada con una interfaz común.
20
Strategy - Solución
«interface»
ISalePricingStrategy
{ {
return s.getPreDiscountTotal() * percentage pdt := s.getPreDiscountTotal()
} if ( pdt < threshold )
return pdt
else
return pdt - discount
}
21
Strategy – Solución (2)
El objeto estrategia es ligado al objeto contexto (es decir
al objeto sobre el cual se aplica el algoritmo. Ej, sale)
lineItems[ i ] : :PercentDiscount
s : Sale
SalesLineItem PricingStrategy
t = getTotal
{ t = pdt * percentage }
loop st = getSubtotal
t = getTotal( s )
22
La referencia de Sale es
hacia la interfaz, no hacia la Sale needs attribute
clase concreta. visibility to its Strategy
Sale
«interface»
date 1 ISalePricingStrategy
...
pricingStrategy getTotal( Sale ) : Money
getTotal()
...
getTotal()
PercentDiscount AbsoluteDiscount
{
PricingStrategy OverThreshold
...
PricingStrategy
return pricingStrategy.getTotal( this ) percentage : float
discount : Money
} getTotal( Sale ) : Money threshold : Money
23
Quién debería crear la estrategia? Una clase
Factory – singleton
1 El cambio de política es
PricingStrategyFactory
frecuente (incluso en
instance : PricingStrategyFactory horas), no es deseable
mantenerla en caché
getInstance() : PricingStrategyFactory sino leerla cada vez y
de una fuente externa.
getSalePricingStrategy() : ISalePricingStrategy
getSeniorPricingStrategy() : ISalePricingStrategy
...
{
String className = System.getProperty( "salepricingstrategy.class.name" );
strategy = (ISalePricingStrategy) Class.forName( className ).newInstance();
return strategy;
}
24
Cuando se crea una venta, ella puede
inicializar su estrategia de precios.
1
:Register
:PricingStrategyFactory
makeNewSale
create :Sale
ps =
getSalePricingStrategy
create(percent) ps : PercentDiscount
PricingStrategy
25