Está en la página 1de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

inShare

En este tutorial de ABAP Objects conoceremos conceptualmente los patrones de diseo y


aprenderemos cmo implementar, paso a paso, el patrn de diseo "decorator", y probaremos
su uso mediante un programa ejemplo en ABAP.
Los patrones de diseo son modelos ("frameworks") de diseo estandarizados, utilizados en la programacin orientada a
objetos, que buscan ofrecer una solucin flexible, prototipada y reusable a ciertos problemas de diseo que ocurren en forma
recurrente en un determinado contexto. Cuando se utilizan de manera correcta, los patrones de diseo ayudan a lograr un
software reutilizable y mantenible, aumentando la extensibilidad y la portabilidad del sistema.
Los patrones de diseo tienen que ver fundamentalmente con el diseo y la interaccin de los objetos, y son utilizados a travs
de todo el espectro de entornos OO. El presente artculo analizar la implementacin en el mundo de ABAP OO, paso a paso,
de un patrn de diseo conocido como "Decorator", a travs de un ejemplo. Una vez explicada en forma conceptual la solucin
y su implementacin en ABAP se lo testear en un programa de prueba.
La utilizacin de patrones de diseo exige conocer las caractersticas particulares del entorno OO que se est utilizando;
en otras palabras, es necesario conocer a qu paradigma dentro del mundo de objetos pertenece ABAP OO, y algunas
consideraciones tericas del patrn de diseo "decorator" en particular. Como se ver en la prxima seccin, no todos los
lenguajes OO organizan el conocimiento de la misma manera, y hay cuestiones de jerarqua de clases, herencia, y conducta del
compilador que afectan el fucnionamiento de los patrones.
En virtud de ello, antes de desarrollar el ejemplo haremos una breve clasificacin de los distintos paradigmas en los lenguajes
de programacin orientados a objetos. No es el alcance de este tip explicar estos paradigmas en detalle, sino identificar en qu
grupo se encuentra ABAP Objects. Si el lector se encuentra familiarizado con los distintos paradigmas de los lenguajes
orientados a Objetos, puede omitir la lectura de las dos prximas secciones.

Overview de los diferentes paradigmas de los lenguajes orientados a objetos


Los lenguajes de programacin orientados a objetos se pueden clasificar en dos grupos, dependiendo de qu manera organizan
el conocimiento:
Por una parte estn los lenguajes que organizan el conocimiento de manera jerrquica, mediante clases, y por otra, los que lo
hacen a travs de prototipos.
El primer caso, por ejemplo, es el de los lenguajes ms populares como Java, VB.Net , Smalltalk, C++, Objective-C. Abap OO
tambin pertenece a este grupo. El segundo grupo, que utiliza prototipos, est compuesto por lenguajes menos conocidos
como "Self".
Dentro de los lenguajes que conforman el primer grupo se pueden encontrar dos grandes divisiones: lenguajes tipados y notipados:
Los tipados son aqullos en que el compilador verifica tipos. Cuando se define un atributo o parmetros de entrada o
salida del mtodo de una clase en Java por ejemplo, se debe especificar de qu tipo son dichos parmetros.
En los no-tipados, no existen los tipos. El lenguaje no controla los tipos de variable que declara. Este es el caso de
Smalltalk y Objective-C, por ejemplo.
Abap OO pertenece al grupo de los tipados, de hecho, quienes hayan programado en Abap OO y Java, puede apreciar
que tienen muchas similitudes y sto se debe a que ambos pertenecen al mismo paradigma.
Dada la naturaleza de cada grupo, la implementacin de un patrn de diseo depende del paradigma al cual pertenezca el
lenguaje . En el caso de los tipados, como el compilador verifica tipos, es necesario heredar de una superclase o
implementar una interfaz para que dos objetos sean polimrficos.Este es el caso de Abap Objects. En contraste, los
lenguajes no tipados, al no tener "tipos", dicha superclase o interfaz NO es necesaria para que dos objetos sean polimrficos.

Pag. 1 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator


Generalidades de los patrones de diseo
Como se dijera en la introduccin, un patrn de diseo es un modelo de solucin reusable y prototipada a un problema de diseo
que se plantea una y otra vez en forma recurrente dentro del mundo de la programacin orientada a objetos. La definicin de un
patrn de diseo incluye:
1) Nombre del patrn: Consiste en una o dos palabras que describen el problema de diseo.
2) El problema: Especifica cundo aplicar el patrn y explica el contexto.
3) La solucin: No describe un diseo concreto ni una implementacin en particular, ya que el mismo se puede aplicar en
diferentes situaciones. En cambio, el patrn provee una descripcin abstracta de un problema de diseo y de qu manera un
conjunto de elementos (clases y objetos) lo resuelven.
4) Las consecuencias: Son los resultados que se obtienen al aplicar un patrn. Incluyen su impacto en la flexibilidad,
extensibilidad y la portabilidad del sistema.

Objetivo y necesidad del patrn de diseo Decorator


Supngase que se desea agregar a la vista de un texto un botn, un scroll, un borde, etc. Imaginemos un contexto donde la
vista no puede tener un borde por defecto porque tal vez no se lo necesite o se requiera otro tipo de borde.
Programar distintas vistas que tengan las distintas funciones (vista con scroll; vista con scroll y borde; vista con borde, etc) es
una tarea ardua y una solucin muy poco mantenible.. Esto ocurre, en primer lugar, porque se debera programar una clase
diferente para cada tipo de combinacin existente, lo cual es insostenible (con 5 elementos adicionales como scroll, borde, input,
text box y table existen 31 combinaciones posibles! ). En segundo lugar, si surge una nueva funcionalidad (un button en la vista
por ejemplo), es tanto el nuevo cdigo que se debe programar que resulta inmantenible. Heredar el borde de una clase es otra
solucin incorrecta, ya que todas las subclases heredaran el borde. Esto es inflexible, porque la eleccin se llevara a cabo
nuevamente de forma esttica.
Decorator es un patrn de diseo que resuelve el problema de aadir dinmicamente funcionalidades adicionales a un objeto.
Para ello, propone una solucin al problema que consiste en encapsular la vista de texto en otro objeto que agrega el
borde. En trminos de programacin dicha encapsulacin es una relacin de composicin, la cual mediante polimorfismo, se
puede llevar a cabo de manera dinmica.
Si bien en el el presente tutorial se va a explicar el patrn "decorator", existen muchos otros como por ejemploSingleton,
Composite, State, Strategy y Template Method. Cada uno propone una solucin general para un problema particular recurrente
en diseo.

Enunciado del ejercicio a desarrollar


Se requiere armar el pedido de un caf para el bar El almacn del buen Caf. En este bar un caf puede ser de diferente tipo:
Cappuccino, Caf Latte, Americano, Ristretto, etc.
Al caf en cuestin se le pueden agregar distintos ingredientes, como por ejemplo: crema,chocolate, canela, leche, etc. Es
vlido agregar el mismo ingrediente dos veces (sera algo como doble crema por ejemplo). Cada tipo de caf tiene un precio y
cada tipo de ingrediente tiene otro. Se requiere obtener el precio total y la descripcin total del pedido.
Por ejemplo si el pedido est formado por el caf Cappuccino ($11) y los ingredientes crema ($1) y canela ($0.5). La descripcin
y precio deberan ser: Cappuccino, crema, canela y $12.5, respectivamente. Si el mismo ingrediente se encuentra dos veces,
no es necesaria la palabra doble. Si el pedido consiste en un Ristretto ($15) con doble crema ($1), alcanza con que la
descripcin sea: Ristretto, crema, crema y el precio: $17.

Pag. 2 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

Anlisis de cmo se va a utilizar decorator


Supongamos que "El almacn del buen Caf" tiene un pedido Cappuccino con los ingredientes crema ycanela. Podemos
pensar que los ingredientes son decoradores del cappuccino. En primer lugar, el cliente desea un Cappuccino, entonces se
crea un objeto cappuccino. Luego el cliente quiere crema, entonces se crea dicho objeto ingrediente (crema) y se hace que
decore al cappuccino. En trminos de programacin se va a tener un objeto crema que tiene un objeto
cappuccino (composicin).

Finalmente el cliente quiere canela, entonces se crea el objeto canela y se lo compone con la crema.

El cmputo de la descripcin total se obtendr de manera recursiva como se puede ver en el siguiente diagrama de secuencia:

El clculo del precio final del pedido se obtendr de forma anloga. El mtodo get_price() en lugar de retornar la concatenacin
de dos strings, va a devolver la suma de dos precios.
A continuacin se ilustra cules son las relaciones de las clases que permiten la solucin del enunciado:

Pag. 3 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

Implementacin de la solucin en Abap OO


Planteado el enunciado del problema a resolver, en los prximos pasos se va a implementar la solucin en ABAP.
Para ello se van a crear las tres clases, y se definirn los atributos y los mtodos correspondientes. Finalmente, se crear un
programa de prueba para testear la solucin.
Nota: El presente tip supone que el lector ya se encuentra familiarizado en cmo crear clases,
definir mtodos y atributos. Si ste no es el caso, es recomendable la lectura del tip Tutorial ABAP
Objects: Parte 2, en donde aprender esos conceptos necesarios para el seguimiento del
presente Tutorial.
En este Tutorial, se crearn las clases de manera global, mediante la transaccin SE80 o SE24. De todas maneras, si el lector
lo desea, puede optar por llevar a cabo la creacin de las mismas de forma local en un programa.
Los pasos para la implementacin de la solucin son los siguientes:
1) Se crea la clase Z_CAFE en la transaccin SE80 o SE24.
2) Una vez creada la clase Z_CAFE, en la solapa de Interfaces se declara la interfaz Z_BEBIDA y se hace doble-click para
crearla:

Pag. 4 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

3) Luego dentro de la interfaz Z_BEBIDA, se hace click en la solapa Atributes y se declaran los
atributosdescription y price como variables de instancia con los tipos asociados que se muestran a continuacin:

Para el tipo asociado a price se eligi un elemento de dato que tiene el siguiente formato:

Elegir algn elemento de dato que tenga caractersticas similares. Si tiene las tablas de vuelos (SPFLI, SFLIGHT, SBOOK)
puede elegir el elemento de dato S_PRICE.
4) Se hace click en la solapa de Methods de la interfaz Z_BEBIDA y se declaran los mtodos de instancia:

Pag. 5 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

Se selecciona el mtodo GET_DESCRIPTION y se oprime el botn Parameters. Luego, en la nueva pantalla se define el
parmetro de retorno R_DESCRIPTION.

Anlogamente se define el parmetro de retorno R_PRICE en el mtodo GET_PRICE. Recuerde definir como tipo asociado el
mismo tipo con que defini el atributo. En el caso de este tutorial ser ZGF_COFFEE_PRICE.
5) Se activa la interfaz Z_BEBIDA.
6) Se regresa a la clase Z_CAFE. Como sta implementa la interfaz Z_BEBIDA, debe implementar sus mtodos. Se dice que la
clase Z_CAFE usa los mtodos y los atributos de la interfaz Z_BEBIDA.

7) Se prosigue a escribir la implementacin de los mtodos. Para ello se hace doble-click


enZ_BEBIDA~GET_DESCRIPTION .

Pag. 6 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

Implementacin:
METHOD z_bebida~get_description.
r_description = z_bebida~description.
ENDMETHOD.

Luego se escribe la implementacin del mtodo GET_PRICE de manera anloga.


Implementacin:
METHOD z_bebida~get_price.
r_price = z_bebida~price.
ENDMETHOD.
8) Se agrega el mtodo CONSTRUCTOR en la solapa de Methods y se definen los siguientes parmetros:

La implementacin del mtodo CONSTRUCTOR es la siguiente:

Pag. 7 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

METHOD constructor.
z_bebida~description = i_description.
z_bebida~price

= i_price.

ENDMETHOD.
9) Se activa la clase Z_CAFE.
10) Se crea la clase Z_INGREDIENTE. En la solapa Interfaces (al igual que como se hizo con la claseZ_CAFE), se declara
la interfaz Z_BEBIDA.
11) Dentro de la clase Z_INGREDIENTE, en la solapa de Methods se agregan los
mtodosCONSTRUCTOR y SET_CAFE_COMPUESTO (los mtodos GET_DESCRIPTION y GET_PRICE aparecen
automticamente porque la clase implementa la interfaz, al igual que ocurri con la clase Z_CAFE). En la solapa de atributos se
agrega la variable de instancia cafe_compuesto con el tipo asociado Z_BEBIDA.
La solapa de mtodos quedar como se ilustra a continuacin:

Y la solapa de los atributos, como sigue:

12) Se procede a definir los parmetros de los cuatro mtodos e implementarlos.


12.1) Mtodo CONSTRUCTOR: se realiza exactamente igual al mtodo CONSTRUCTOR de la claseZ_CAFE, con los mismos
parmetros y la misma implementacin (Puede hacer "copy-paste" del cdigo)
12.2) Mtodo SET_CAFE_COMPUESTO:
Parmetros:

Pag. 8 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

Implementacin:
METHOD set_cafe_compuesto.
cafe_compuesto = i_cafe_compuesto.
ENDMETHOD.
12.3) Mtodo GET_DESCRIPTION. En ese caso no hay que definir ningn parmetro ya que los mismos surgen de la
interfaz Z_BEBIDA.
Implementacin:
METHOD z_bebida~get_description.
DATA: desc TYPE string,
desc_final TYPE string.
desc = cafe_compuesto->get_description( ).
CONCATENATE desc z_bebida~description INTO desc_final
SEPARATED BY ', '.
r_description = desc_final.
ENDMETHOD.
12.4) Mtodo GET_PRICE
Implementacin:
METHOD z_bebida~get_price.
DATA: parcial_price
final_price

TYPE zgf_coffee_price,

TYPE zgf_coffee_price.

parcial_price = cafe_compuesto->get_price( ).
final_price = parcial_price + z_bebida~price.
r_price = final_price.

Pag. 9 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

ENDMETHOD.
Nota: Recuerde incluir el elemento de dato correspondiente para las variables parcial_price y final_price.
13) Active la clase Z_INGREDIENTE como ltimo paso del desarrollo.
14) El lector puede testear las clases como desee. A continuacin se muestra el cdigo de un programa Abap de prueba, en
donde se va a realizar la composicin de los objetos a mano para verificar el funcionamiento. Recuerde nuevamente utilizar el
tipo de dato correspondiente para la variable price.
Cdigo ABAP de prueba propuesto:
*&---------------------------------------------------------------------*
*& Report Z_PRUEBA_PEDIDO
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT z_prueba_pedido.
DATA: cappuccino
crema

TYPE REF TO z_ingrediente,

canela

TYPE REF TO z_ingrediente,

description
price

TYPE REF TO z_cafe,

TYPE string,

TYPE zgf_coffee_price.

"***Se crean los objetos


CREATE OBJECT cappuccino
EXPORTING
i_description = 'Cappuccino'
i_price

= '11'.

CREATE OBJECT crema


EXPORTING

Pag. 10 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator

i_description = 'crema'
i_price

= '1'.

CREATE OBJECT canela


EXPORTING
i_description = 'canela'
i_price

= '0.5'.

"Se Realiza la composicion


crema->set_cafe_compuesto(
EXPORTING
i_cafe_compuesto = cappuccino ).
canela->set_cafe_compuesto(
EXPORTING
i_cafe_compuesto = crema ).
"***Se obtiene la descripcion y el precio
description = canela->z_bebida~get_description( ).
price

= canela->z_bebida~get_price( ).

WRITE: 'Descripcion: ',description,


/,'Precio: ',price.

Salida resultante por pantalla:

Pag. 11 de 12

ABAP Objects: Tutorial para implementar el patrn de diseo decorator


Consideraciones adicionales:
1) Notar que en el programa de prueba, la composicin se realiz a mano para testear las tres clases. Se recomienda crear
una clase "armadora" llamada Z_ARMADOR_CAFE que encapsule la composicin de los objetos. La forma de implementar la
clase queda librada al lector.
2) Notar tambin que para poder implementar el patrn se requiri que los objetos de la clase CAFE
e INGREDIENTE sean polimrficos. En los lenguajes tipados, se necesita heredar de una superclase o implementar una interfaz
para que dos objetos sean polimrficos. Es por eso que se us la interfaz BEBIDA.Se podra haber utilizado una clase abstracta,
pero se opt por usar una interfaz ya que no se encuentra una superclase apropiada que tenga como subclases a CAFE e
INGREDIENTE. Igualmente si el lector lo desea, puede probar la alternativa de usar una clase abstracta.
3) Observar que no se cre una clase para cada ingrediente y que las mismas heredan de una superclase INGREDIENTE. Se
cre una nica clase porque todos los ingredientes tienen la misma forma de calcular su costo y su descripcin (mismo
comportamiento). Suponga ahora que el precio de la leche est dado por 50ml y que el cliente puede decidir cuntos ml de leche
quiere. En este caso el precio de la leche va a depender de un atributo adicional que es la cantidad solicitada. Por lo tanto en
este caso tiene sentido crear una clase abstracta INGREDIENTE con subclases LECHE y CANELA por ejemplo.
4) Analizar cmo cambia la implementacin del patrn en los lenguajes no-tipados como Smalltalk. En ese caso no se
necesitara de la interfaz o clase abstracta BEBIDA, ya que en dichos lenguajes no se requiere de herencia para que dos objetos
sean polimrficos. Es por esta razn que se explic a qu paradigma pertenece Abap OO.
5) Observar que para invocar los mtodos get_price() y get_description() se utiliz la forma un_objeto>nombre_interfaz~un_metodo( ). De esta manera queda expuesto el uso de la interfaz, lo cual no es conveniente. Para lograr
una mejor encapsulacin se recomienda el uso de alias. Esto no es ms que un alias para poder llamar al mtodo con otro
nombre. De esta manera, se puede invocar al mtodo medianteun_objeto->un_metodo( ) sin exponer el uso de la interfaz.

Pag. 12 de 12

También podría gustarte