You are on page 1of 13

PATRONES DE DISEO: APLICABILIDAD

Y EJEMPLO EN JAVA.
JNATHAN LVAREZ GONZLEZ.
COD: 108799!88.
"NIVERSIDAD TECNOLGICA DE PEREIRA.
PROGRAMA INGIENER#A DE SISTEMAS Y COMP"TACIN.
IS!$. PROGRAMACIN ORIENTADA A OBJETOS
PEREIRA% MARZO &010.
PATRONES DE DISEO: APLICABILIDAD
Y EJEMPLO EN JAVA.
JNATHAN LVAREZ GONZLEZ.
COD: 108799!88.
MONOGRA'#A:
PATRONES DE DISEO.
INGENIERO:
NGEL A"G"STO AG"DELO ZAPATA.
"NIVERSIDAD TECNOLGICA DE PEREIRA.
PROGRAMA INGIENER#A DE SISTEMAS Y COMP"TACIN.
IS!$. PROGRAMACIN ORIENTADA A OBJETOS
PEREIRA% MARZO &010.
CONTENIDO.
T()* P+,-.*.
1. P*/01.(2 C0(*3-1.*4(2 4
1.1 Mtodo de Fabricacin (Factory
Method)
4
1.2 Singleton. 5
&. P*/01.(2 E2/053/50*4(2 6
2.1 Adaptador (Adapter) 6
2.2 Decorador (Decorator)
$. P*/01.(2 6( C1)710/*)-(./1 !
".1 #$tado$ (State$) !
".2 %b$er&ador (%b$er&er) 11
B-84-1,0*9-*. 1"
PATRONES DE DISEO.
'o$ patrone$ de di$e(o $on )n con*)nto de e$trategia$ o b)ena$ pr+ctica$ ,)e -acilitan el
traba*o a la hora de de$arrollar )na aplicacin en e$pec.-ico. /olo,)ial0ente Los
patrones de diseo son el esqueleto de las soluciones a problemas comunes en el
desarrollo de software.
Se caracteri1an por $er )na agr)pacin de $ol)cione$ a proble0a$ no tri&iale$2
generali1ado$ y aplicable$ para c)al,)ier leng)a*e de progra0acin ,)e traba*e el
paradig0a %rientado a %b*eto$ y ,)e de $ta -or0a $on i0ple0entacione$ re)tili1able$ y
e-ecti&a$2 p)e$ ya $e ha co0probado la $ol)cin de lo$ proble0a$ de -or0a $ati$-actoria.
'o$ patrone$ de di$e(o $e di&iden en tre$ principale$ gr)po$ cla$i-icado$ $eg3n $)$
prop$ito$2 $on conocido$ ade0+$ en honor a $)$ c)atro a)torie$ co0o la banda de lo$
c)atro (4ang o- Fo)r 5 4oF)2 lo$ patrone$ $e cla$i-ican en6
1. 7atrone$ /reacionale$.
2. 7atrone$ #$tr)ct)rale$.
". 7atrone$ de /o0porta0iento.
7or intere$e$ propio$ del c)r$o2 $lo $er+n re$e(ado$ do$ patrone$ de cada cla$e.
1. PATRONES CREACIONALES.
#$t+ndare$ de creacin de cla$e$2 ab$trayendo la -or0a en la ,)e $e crean lo$ ob*eto$.
1.1 '*3/10:* ;'*3/10<=.
#$te patrn $e ba$a en el concepto ,)e )n ob*eto e$peciali1ado $e encarga de in$tanciar
otro$ di-erente$ ob*eto$ y e$to$ proporcionan la inter-a1 del ob*eto recibido.
S)pnga$e )n 0all de co0ida$2 de ello$ e8i$ten de di-erente$ e$peciali1acione$2 co0ida$
t.pica$2 co0ida r+pida2 co0ida$ internacionale$. 'le&ando e$to a la progra0acin
orientada a ob*eto$ obtene0o$ algo c0o e$to6
public abstract class MallComidas {
public abstract String darComida();
}
public class ComidaTipica extends MallComidas {
@Override
public String darComida() {
return "Bandeja paisa.";
}
}
public class Comidaapida extends MallComidas {
public String darComida() {
return "Com!o "am!#rg#esa $ papas %ritas agrandadas.";
}
}
4
Si ,)i$ira0o$ ahora poner en -)nciona0iento n)e$tro pe,)e(o progra0a deber.a0o$
hacer algo co0o e$to6
public class Main {
public static void main( String&' args ) {
MallComidas cena ( null;
))Capric*o es #n dato ingresado por el cliente
if( capric*o.e+#als("comida tipica") ) {
cena ( new ComidaTipica();
}
else if ( capric*o.e+#als("comida rapida") ) {
cena ( new Comidaapida();
}
S$stem.out.println( cena.darComida() );
}
}
'a i0ple0entacin co0o tal no tiene nada errneo. 7roceda0o$ ahora a con$tr)ir n)e$tra
Factor.a y de-inire0o$ de n)e&o n)e$tra cla$e Main.
public class ,actoria {
public static MallComidas crearComida( String capric*o ) {
if( capric*o.e+#als("comida tipica") ) {
return new ComidaTipica();
}
else if ( capric*o.e+#als("comida rapida") ) {
return new Comidaapida();
}
return null;
}
}
public class Main {
public static void main( String&' args ) {
MallComidas cena ( ,actoria.crearComida( "comida tipica" );
S$stem.out.println( cena.darComida() );
}
}
'o ,)e he0o$ logrado ahora e$ )n cdigo 0)cho 0+$ legible2 donde tal co0o $e &e2 )n
patrn Factory elige el ob*eto a in$tanciar y e$conde $te cdigo2 pro0o&iendo el
encap$)la0iento de la$ parte$ 0+$ &ariable$ del $i$te0a9 la cla$e principal: -oco
e*ec)table Main e$ 0)cho 0+$ agradable a &i$ta dada $) notable red)ccin2 l)ego2
35*4>5-(0* 7160+ 106(.*0 31)-6* 2-. .(3(2-6*6 6( 31.13(0 (4 )*44 6( 31)-6* *
-.2/*.3-*0.
1.& I.2/*.3-* ?.-3* ;S-.,4(/1.=.
'a in$tancia 3nica parte de la nece$idad de per0itir )na y $ola )na in$tancia de alg)na
cla$e en e$pec.-ico2 e$to $e logra per0itiendo ,)e $ea la propia cla$e la encargada de
garanti1ar la e8i$tencia de )na 3nica cla$e.
5
'a$ in$tancia$ 3nica$ $on nece$aria$ a 0edida en ,)e )n ob*eto debe controlar el acce$o
a )n 3nico rec)r$o co0o )n archi&o abierto en 0odo e8cl)$i&o2 o bien )n ca$o t.pico
co0o la cone8in a )na ba$e de dato$.
'a i0ple0entacin general de $te patrn $e logra creando la in$tancia de la cla$e por
0edio de )n 0todo de ella 0i$0a y el acce$o a lo$ con$tr)ctore$ de la 0i$0a e$
reg)lada por 0edio de atrib)to$ co0o pri&ado. #n *a&a2 )na i0ple0entacin correcta de
$ingleton e$ la prop)e$ta por ;ill 7)gh6
public class Singleton {
private Singleton() {}

public static Singleton get-nstance() {
return Singleton"older.instance;
}

private static class Singleton"older {
private final static Singleton instance ( new Singleton();
}
}
#8i$ten otra$ &ariante$ de e$ta i0ple0entacin en e$pecial2 por el te0a de la
conc)rrencia2 $i$te0a$ 0)lti<hilo$. 7ero la e$encia del patrn no $e degrada.
&. PATRONES ESTR"CT"RALES.
S) -in e$ b)$car por 0edio del e$t)dio de la$ relacione$ entre lo$ ob*eto$2 la 0e*or -or0a
de con$eg)ir ,)e ca0bio$ en lo$ re,)i$ito$ de la aplicacin no oca$ionen ca0bio$ en la$
relacione$ entre lo$ ob*eto$2 logrado por la$ inter-ace$ ,)e $oportan lo$ ob*eto$.
&.1 A6*7/*610 ;A6*7/(0=.
=n patrn Adaptador tal co0o $) no0bre lo $)giere2 $on )tili1ado$ para adaptar )n ob*eto
a otro2 o bien con&ertirlo.
7or lo reg)lar2 por 0edio de a$ignacione$ $e logra )n $ol)cin2 $in e0bargo2 )n patrn de
adaptacin2 e$ )na -or0a 0)cho 0+$ li0pia y re)tili1able.
Sig)iendo con n)e$tro e*e0plo de 0all de co0ida2 $)pnga$e ,)e ahora po$ee0o$
&ario$ de ello$2 y n)e$tro $i$te0a de i0ple0entacin con$i$te en algo 0+$ ad0ini$trati&o
y general6
public abstract class MallComida {
protected int n#meroTra!ajadores;
protected String especiali.acion;
public abstract int get/#mTra!ajadores();
public abstract String get0speciali.acion();
}
Ahora $)pnga$e ,)e dado n)e$tro 8ito2 co0pra0o$ otra dependencia de co0ida2 la
c)al tiene i0ple0entado $) propio $i$te0a y l)ego n)e$tro$ ob*eto$ (dependencia$) $on
di-erente$ a la ad,)irida6
public class Comederos1#an {
private int n#mero1#ansitos ( 2;
6
private String ric#ra1#an3 ( "4asta -taliana";
private String ric#ra1#an5 ( "6inos C*ilenos";
public int dame0l/#mero1#ansitos() {
return n#mero1#ansitos;
}
public String dame7aic#ra1#an3() {
return ric#ra1#an3;
}
public String dame7aic#ra1#an5() {
return ric#ra1#an5;
}
}
/o0o $e &e2 la$ i0ple0entacione$2 para e$te ca$o $encillo2 &ar.an en $)$ no0bre$ y
n30ero de 0todo$. 'a $ol)cin dr+$tica$ con$i$te en o ca0biar por co0pleto n)e$tra
i0ple0entacin2 o bien la de n)e$tra n)e&a dependencia. 'a $ol)cin elegante con$i$te
en *6*7/*0 4* .5(@* 6(7(.6(.3-* * 4*2 >5( <* /(.()12:
public class Comederos1#an8dapter extends MallComida {
private Comederos1#an comedero1#an;
public Comederos1#an8dapter(Comederos1#an cj) {
comedero1#an ( cj;
}
@Override
public String get0speciali.acion() {
return comedero1#an.dame7aic#ra1#an3() 9 "$ " 9
comedero1#an.getic#ra1#an5();
}
@Override
public int get/#mTra!ajadores() {
return comedero1#an.dame7os/#mero1#ansitos();
}
}
>te$e ,)e he0o$ creado )na cla$e adaptadora ,)e no$ 0oldea o a*)$ta otro ob*eto
externo a n)e$tro$ ob*eto$ conocidos. ')ego2 para obtener n)e$tro n)e&o ob*eto2 e$ tan
$i0ple y elegante co0o e$to6
MallComida comedero1#an ( new Comederos1#an8dapter(new Comederos1#an());
S$stem.out.println( comedero1#an.get0speciali.acion() );
S$stem.out.println( comedero1#an.get/#mTra!ajadores() );
&.& D(310*610(2 ;D(310*/10=.
'o$ decoradore$ $on i0ple0entado$ en -)ncin de e&itar crear 03ltiple$ $)bcla$e$. 7or
e*e0plo $)pnga$e la cla$e /el)lar9 $i $e no$ e$ nece$ario tener )n cel)lar con c+0ara la
$ol)cin $eria crear la $)bcla$e /el)lar/a0ara ,)e herede de /el)lar. De ig)al -or0a $i
$e ,)iere la -)ncionalidad de ?i-i2 $e crear.a la $)bcla$e /el)lar@i-i.
#l proble0a llega c)ando ,)ere0o$ ahora )n cel)lar tanto con ?i-i co0o con c+0ara o
bien 03ltiple$ de $ta$ -)ncionalidade$.

'a creacin de &aria$ $)bcla$e$ para la $ol)cin de cada proble0a partic)lar no $e


con&ierte en algo e-ecti&o9 #l patrn decorador e&ita e$to creando para e$te ca$o )na
cla$e ab$tracta /el)larDecorador y herededando de ella2 /a0araDecorator y
@i-iDecorador. A,)ella encap$)lar.a el co0porta0iento de /el)lar y a(adir.a por 0edio
de co0po$icin rec)r$i&a tanta$ -)ncionalidade$ co0o $e ,)ieran. 'o anterior $er.a6
Cel#lar cel#lar ( ne: Cel#lar();
cel#lar ( ne: ;i%i<ecorator( cel#lar );
cel#lar ( ne: Camara<ecorator( cel#lar );
cel#lar ( ne: Camara<ecorator( cel#lar );
Seg3n el e*e0plo2 ahora po$eer.a0o$ )n cel)lar con ?i-i y do$ c+0ara$.
#l patrn decorador e$ plena0ente &i$ible en la librer.a gr+-ica de *a&a ( S@A>4 B A@C)2
por e*e0plo c)ando ,)ere0o$ agregar )na barra de de$pla1a0iento ($croll) a alg)no de
n)e$tro co0ponente$ (D/o0ponent$).
1Ta!le ta!le ( ne: 1Ta!le(=>?);
1Scroll4ane ta!laScroll ( ne: 1Scroll4ane( ta!le );
6entana4rincipal.add( ta!laScroll );
>te$e ,)e el DScroll7ane e$ el decorador del co0ponente DCable.
=n patrn decorador -or*a )n cdigo -le8ible ante ca0bio$ a(adiendo la po$ibilidad
din+0ica de agregacin de n)e&o$ e$tado$ y -)ncionalidade$ a )n ob*eto.
$. PATRONES DE COMPORTAMIENTO.
;a$ado en la di0en$in te0poral2 lo$ patrone$ de co0porta0iento e$t)dian la relacin de
la$ lla0ada$ entre di-erente$ ob*eto$.
$.1 E2/*61 ;S/*/(=.
/)ando )n $i$te0a ) ob*eto ba$a $) co0porta0iento $eg3n )n patrn de e$tado$2 $)
co0ple*idad al ig)al ,)e $) 0anteni0iento a)0enta al intentar controlar toda$ la$
&ariacione$ de e$tado$ en )n $olo blo,)e. #l patrn #$tado propone crear b+$ica0ente
tanto$ ob*eto$ co0o e$tado$ a ad0ini$trar $ean nece$ario$.
S)pnga$e ,)e ahora ba$a0o$ n)e$tro $i$te0a de 0all de co0ida$ en do$ e$tado$2
3(00*61 < *8-(0/1% con ello podre0o$ de-inir alg)no$ co0porta0iento$ co0o *80-0;=%
3(00*0;=% 4-)7-*0;= :
public class MallComida {
private String estado;
public void a!rirMall() {
if( estado.e+#als("cerrado") ) {
S$stem.out.println( ""emos a!ierto" );
}
else if( estado.e+#als("a!ierto") ){
S$stem.out.println( "ealmente $a *emos a!ierto" );
}
}
8
public void cerrarMall() {
if( estado.e+#als("cerrado") ) {
S$stem.out.println( "ealmente $a *emos cerrado" );
}
else if( estado.e+#als("a!ierto") ){
S$stem.out.println( ""emos cerrado" );
}
}
public void limpiar() {
if( estado.e+#als("cerrado") ) {
S$stem.out.println( "0stamos limpiando a*ora mismo@" );
}
else if( estado.e+#als("a!ierto") ){
S$stem.out.println( "8An no *emos cerrado> no podemos limpiar
con clientes presentes." );
}
}
}
>)e&a0ente2 la i0ple0entacin no e$ errnea. 7ero nte$e ,)e por e*e0plo no $e no e$
po$ible li0piar() n)e$tro 0all $in a3n haberlo cerrado2 a$. ,)e pri0ero deber.a0o$
cerrar() y l)ego li0piar(). Ade0+$ la$ co$a$ $e co0plican 0)cho 0+$ en el ca$o ,)e
h)bie$e pre$ente 0+$ de )n e$tado.
#l patrn de e$tado entra en e$te 0o0ento2 para ello $er+ nece$ario entonce$ crear )na
cla$e ab$tracta con todo$ n)e$tro$ co0porta0iento$ 2(,A. 5. (2/*61 y creare0o$
ade0+$ 18B(/12 710 3*6* (2/*61 712-84(.
public abstract class 0stadosMall {
public abstract void a!rirMall();
public abstract void cerrarMall();
public abstract void limpiar();
}
public class 0stado8!rirMall extends 0stadosMall {
private MallsComidas mall;
public 0stado8!rirMall( MallsComidas mall ) {
this.mall ( mall;
}
public void a!rirMall() {
S$stem.out.println( "ealmente $a *emos a!ierto@" );
}
public void cerrarMall() {
S$stem.out.println( "0stamos cerrando> por %in termino el dia@" );
mall.set0stado8ct#al( new 0stadoCerrarMall( this.mall ) );
}
public void limpiar() {
S$stem.out.println( "Cerraremos $ procederemos a limpiar@" );
mall.set0stado8ct#al( new 0stadoCerrarMall( this.mall ) );
mall.limpiar();
}
}
9
public class 0stadoCerrarMall extends 0stadosMall {
private MallsComidas mall;
public 0stadoCerrarMall(MallsComidas mall) {
this.mall ( mall;
}
public void a!rirMall() {
S$stem.out.println( "0stamos a!riendo> Bs#spiroB serC #n dia
largo" );
mall.set0stado8ct#al( new 0stado8!rirMall( this.mall ) );
}
public void cerrarMall() {
S$stem.out.println( "ealmente $a *emos cerrado@" );
}
public void limpiar() {
S$stem.out.println( ""emos limpiado@@ $a nos vamos@" );
}
}
Ahora2 n)e$tro$ 0todo$ logran )na red)ccin notable6
public class MallComida extends 0stadosMall {
private 0stadosMall estado8ct#al;
public MallsComidas() {
estado8ct#al ( new 0stadoCerrarMall( this );
}
public void set0stado8ct#al(0stadosMall em) {
estado8ct#al ( em;
}
public void a!rirMall() {
this.estado8ct#al.a!rirMall();
}
public void cerrarMall() {
this.estado8ct#al.cerrarMall();
}
public void limpiar() {
this.estado8ct#al.limpiar();
}
}
E de$de l)ego2 dada la i0ple0entacin ahora e$ po$ible li0piar() el 0all a3n c)ando e$te
abierto2 p)e$to ,)e en #$tadoAbrirMall pri0ero $e cierra() y l)ego $e li0pia.
MallComida mall ( ne: MallComida();
mall.a!rirMall();
mall.limpiar();
mall.cerrarMall(); )) O!tendremos #n mensaje de +#e el mall $a
esta cerrado.
10
$.& O82(0@*610(2 ;O82(0@(02=.
'a idea de lo$ ob*eto$ ob$er&adore$2 e$ de po$eer )n ob*eto de 0odo tal ,)e c)ando e$t
ca0bie indi,)e a $)$ ob$er&adore$ $) ca0bio.
Se di$ting)en entonce$ do$ cla$e$ de ob*eto$2 412 182(0@*6122 ,)iene$ po$een 0todo$
,)e indican a otro$ ob*eto$ $) ca0bio y 412 182(0@*610(2 ,)iene$ reciben la noti-icacin
de )n ob*eto ha $)-rido )n ca0bio.
S)pnga$e )n relo*. =n ob*eto de lla0ado Ce0pori1ador noti-ica a ob*eto$ ,)e lo ob$er&an
co0o Felo*Digital y:o Felo*Analogico ,)e algo ha ca0biado2 por e*e0plo2 ha tran$c)rrido
)n 0in)to.
Dando contin)acin a n)e$tro e*e0plo de 0all de co0ida$. 7en$e0o$ ahora en ,)e
tene0o$ la necesidad de $aber la 0e$a oc)pada in0ediata0ente por )n n)e&o cliente.
Ceniendo 182(0@*610(2 ,)e no$ noti-i,)en e$te ca0bio podre0o$ a0bientar la 0e$a
adaptando la cale-accin2 y a&i$ando a 0e$ero$ del n)e&o cliente y $) 0e$a
corre$pondiente6
public interface -O!servador {
public void n#evoCliente( 7istaMesas o!servado> int n#mMesa );
}
public class /#evoClienteO!servador implements -O!servador {
@Override
public void n#evoCliente(7istaMesas o!servado> int n#mMesa) {
S$stem.out.println( "Dn n#evo cliente *a llegado a la mesa " 9
n#mMesa );
}
}
public class Cale%accionO!servador implements -O!servador {
@Override
public void n#evoCliente(7istaMesas o!servado> int n#mMesa) {
S$stem.out.println( "7a cale%acciEFn de la mesa " 9 n#mMesa 9 " *a
sido reg#lada" );
}
}
public class MeseroO!servador implements -O!servador {
@Override
public void n#evoCliente(7istaMesas o!servado> int n#mMesa) {
S$stem.out.println( "0l mesero se *a dirigido a la mesa " 9 n#mMesa
9 " $ *a tomado la orden" );
}
}
public class 7istaMesas {
private -O!servador&' o!servadores;
public 7istaMesas( int n#mO!servadores ) {
o!servadores ( new -O!servador&n#mO!servadores';
}
public void agregarMesa( int n#mMesa ) {
for( -O!servador io! G o!servadores ) {
io!.n#evoCliente(this> n#mMesa);
}
}
11
public void agregarO!servador( -O!servador o!servador ) {
for( int i(H; i I o!servadores.lengt* ; i99 ) {
if( o!servadores&i' (( null ) {
o!servadores&i' ( o!servador;
return;
}
}
}
}
'o ,)e he0o$ hecho e$ crear )na inter-a1 ,)e 0oldee n)e$tro$ ob$er&adore$2 lo$ ob*eto$
ob$er&adore$ ,)e i0ple0enten e$ta inter-a1 y )n ob*eto 'i$taMe$a$ ,)e haga )$o de lo$
ob$er&adore$. =n e*e0plo de la aplicacin e$ el $ig)iente6
7istaMesas listaMesas ( new 7istaMesas(2);
listaMesas.agregarO!servador( new /#evoClienteO!servador() );
listaMesas.agregarO!servador( new Cale%accionO!servador() );
listaMesas.agregarO!servador( new MeseroO!servador() );
listaMesas.agregarMesa(2);
listaMesas.agregarMesa(J);
#l re$)ltado en pantalla $er.a6
=n n)e&o cliente ha llegado a la 0e$a "
'a cale-accin de la 0e$a " ha $ido reg)lada
#l 0e$ero $e ha dirigido a la 0e$a " y ha to0ado la orden
=n n)e&o cliente ha llegado a la 0e$a 6
'a cale-accin de la 0e$a 6 ha $ido reg)lada
#l 0e$ero $e ha dirigido a la 0e$a 6 y ha to0ado la orden
#l patrn ob$er&ador e$ -rec)ente0ente i0ple0entado2 lo pode0o$ &er por e*e0plo2 de
n)e&o2 en la$ librer.a$ S@A>4<A@C de *a&a y en e$pecial en todo lo ,)e tenga ,)e &er
con di-erente$ tipo$ de e&ento$. =n ob*eto ob$er&ador e$ conocido ta0bin co0o )n
li$tener2 e$c)chador.
12
BIBLIOGRA'IA.
4%%D2 >ACGA>. #n A;M De&eloper@orH$. Fi&e 0ore 7G7 de$ign pattern$. Ien lineaJ.
Di$ponible en6 http6::???.ib0.co0:de&eloper?orH$:open$o)rce:library:o$<php<
de$ignpattern$:
G#F>A>2 '=AS. #n So-t?are 4)i$ho. Factory pattern 5 7atrone$. Ien lineaJ. Di$ponible
en6 http6::$o-t?are.g)i$ho.co0:patrone$<de<di$eno<-actory<pattern
AFK=AC#/C=FA D# SASC#MAS A>FLFMACA/%S. Decorador (4oF) agregando
re$pon$abilidade$ a )n ob*eto de -or0a din+0ica. Ien linea J. Di$ponible en6
http6::0etodologia$de$i$te0a$.blog$pot.co0:2MM!:M1:decorador<go-<agregando.ht0l
A'NAF#O AS%F#E2 DANAD. #n Mi Fincn en Anternet. 7atrone$ de di$e(o para torpe$ 5
1P 5 2
a
parte. Ien lineaJ. Di$ponible en6 http6::da&ida$orey.net:!M:patrone$<di$eno<para<
torpe$<1
7ACF%>#S D# DAS#Q%. #n @iHipedia. 7atrone$ de di$e(o. Ien lineaJ. Di$ponible en6
http6::e$.?iHipedia.org:?iHi:7atrnRdeRdi$e(o
C%FF#S 'A4%S2 MA>=#'. #n #l Fincn del 7rogra0ador. Antrod)ccin al di$e(o con
patrone$. Ien lineaJ. Di$ponible en6 http6::???.elrincondelprogra0ador.co0:de-a)lt.a$pS
idT2UVpagTartic)lo$:leer.a$p
C#D#S/GA2 >A/%'WS. #n Micro$o-t De&eloper >et?orH. XK) e$ )n 7atrn de Di$e(oS.
Ien lineaJ. Di$ponible en6 http6::0$dn.0icro$o-t.co0:e$<e$:library:bbU224M.a$p8

You might also like