Seguimos buscando a Arshak. Ayudanos compartiendo!
Encuesta no oficial de docentes
Resultados de la encuesta no oficial de docentes
Probaste el SIGA Helper?

Donar $100 Donar $200 Donar $500 Donar mensualmente


Enviar respuesta 
 
Calificación:
  • 0 votos - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Buscar en el tema
Patron de diseño "State"
Autor Mensaje
cuchodelosdecadentes Sin conexión
Campeon del cubo Rubik
soooomos los piratas ...
****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 195
Agradecimientos dados: 88
Agradecimientos: 6 en 6 posts
Registro en: Dec 2011
Mensaje: #1
Patron de diseño "State" Ejercicios Diseño de Sistemas
Hola a todos.

Entiendo en general como usar y cuando usar el patron ( o sea, entiendo la parte de delegar, encapsular y demas )
Pero hay algunas cosas que no me quedan claras.

Piensen en un banco. Tengo cuentas. Una cuenta puede estar en diferentes estados. O sea, normal(luego de haberla creado), silver(saldo de mas de 20k y menos de 50k), y gold ( saldo de mas de 50k).
Obviamente, en una cuenta puedo depositar y extraer.
Cada vez que deposito o extraigo hay que ver en que estado queda la cuenta.

1) Quien tiene la responsabilidad de hacer el cambio de estado ? Justifique =)
a) La clase Cuenta ( a traves de ifs internos luego de realizar tanto extract como deposit )
b) Cada estado ( haciendo uso del metodo pasarAEstado: de la clase cuenta )

2) Vi que algunas implementaciones usan una variable de instancia por cada estado en la clase Cuenta.
O sea, en vez de tener la variable estado, tiene una referencia a cada estado ( normal, silver, gold).
Porque es necesario eso ? No hay que tener solamente una referencia a estado y listo ?

3) Cada estado deberia tener una referencia a la clase Cuenta, o la clase cuenta deberia pasarse a si misma como parametro cuando delega una operacion a un estado ?
O sea, es mejor
a) this.estado.hacerExtraccion(this) ( aca la cuenta se pasa a si misma como parametro cuando llama a estado)
b) this.estado.hacerExtraccion() ( aca, obviamente, como dije, cada estado tiene una referencia a la cuenta )

Justifique =)

Saludos y gracias desde ya.
Otros adjuntos en este tema
.jpg  DSC_0074.JPG ( 357,1 KB / 654) por reLlene
.jpg  DSC_0075.JPG ( 674,06 KB / 640) por reLlene
.jpg  DSC_0076.JPG ( 478,33 KB / 633) por reLlene
16-02-2015 05:40
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Dios Sin conexión
Presidente del CEIT
.
********

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 1.057
Agradecimientos dados: 32
Agradecimientos: 160 en 132 posts
Registro en: Dec 2011
Mensaje: #2
RE: Patron de diseño "State"
1) El patrón state en sí no especifica qué objeto debería ser el encargado de los cambios de estados, así que depende del contexto. En todo caso, en general es más flexible (y esperable y hasta deseable) que el objeto de estado sea el que determine cuál es el próximo estado en el que va quedar. Teniendo en cuenta que el objetivo de la clase State es modificar el comportamiento de otra clase sin modificar esa clase, poner muchos ifs dentro de la clase hace que por cada nuevo estado posible haya que modificar la clase. En cambio delegando en el estado quedan cosas como, por ejemplo:



//En alguna parte del código...
this.estado.hacerDeposito(this, 1000);

...

//Un estado concreto, digamos silver
public class Silver extends EstadoCuenta {
public void hacerDeposito(Cuenta cuenta, int monto)
{
cuenta.saldo += monto; //O de alguna forma más elegante.
if (cuenta.saldo >= 50000)
cuenta.pasarAEstado(new Gold());
}
}



Probablemente lo que escribí no sea correcto en ningún lenguaje, pero es como para dar un ejemplo.

2) No sé. No es "necesario" tener una referencia a cada estado si es el estado mismo el que se ocupa de cambiarlo.

3) Te la medio respondí con el código en 1): cada cuenta debería pasarse a sí misma para que el estado pueda hacer la operación de cambio de estado en la cuenta.


Por lo menos, así lo veo yo sic sic sic sic

«(…)Se arman paquetes… ¿eh?… tecnológicos… tecnológicos portes de… en donde están… este… interrelacionados con las otras capas.(…)»
(Este mensaje fue modificado por última vez en: 16-02-2015 11:24 por Dios.)
16-02-2015 11:15
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
cuchodelosdecadentes Sin conexión
Campeon del cubo Rubik
soooomos los piratas ...
****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 195
Agradecimientos dados: 88
Agradecimientos: 6 en 6 posts
Registro en: Dec 2011
Mensaje: #3
RE: Patron de diseño "State"
(16-02-2015 11:15)Dios escribió:  1) El patrón state en sí no especifica qué objeto debería ser el encargado de los cambios de estados, así que depende del contexto. En todo caso, en general es más flexible (y esperable y hasta deseable) que el objeto de estado sea el que determine cuál es el próximo estado en el que va quedar. Teniendo en cuenta que el objetivo de la clase State es modificar el comportamiento de otra clase sin modificar esa clase, poner muchos ifs dentro de la clase hace que por cada nuevo estado posible haya que modificar la clase. En cambio delegando en el estado quedan cosas como, por ejemplo:



//En alguna parte del código...
this.estado.hacerDeposito(this, 1000);

...

//Un estado concreto, digamos silver
public class Silver extends EstadoCuenta {
public void hacerDeposito(Cuenta cuenta, int monto)
{
cuenta.saldo += monto; //O de alguna forma más elegante.
if (cuenta.saldo >= 50000)
cuenta.pasarAEstado(new Gold());
}
}



Probablemente lo que escribí no sea correcto en ningún lenguaje, pero es como para dar un ejemplo.

2) No sé. No es "necesario" tener una referencia a cada estado si es el estado mismo el que se ocupa de cambiarlo.

3) Te la medio respondí con el código en 1): cada cuenta debería pasarse a sí misma para que el estado pueda hacer la operación de cambio de estado en la cuenta.


Por lo menos, así lo veo yo sic sic sic sic

Hola Dios. Yo también pensaba igual que vos. Para mi lo ideal era delegar la responsabilidad de cambio de estados a cada una de las clases estado.
Pero haciendo algunos ejemplos, veo que si hago esto, si despues quiero agregar un nuevo estado, tengo que modificar cada implementacion de cada clase estado. Es decir, el agregar un nuevo estado me obliga a "abrir" el codigo de cada clase estado para agregar la parte que haria transicionar a ese nuevo estado.
En cambio si en la clase contexto( Cuenta para este caso) me encargo de esa transicion, entonces, cuando agrega un nuevo estado ( clase), solo debo modificar la clase contexto y no cada una de las clases estado.
O sea, la clase Cuenta, haría lo siguiente:
Por cada operacion solicitada:
1) delegar la operacion al estado
2) decidir transicion

Fijate que en ambos estoy yendo en contra del principio de diseño "cerrada para modificaciones".
Eso es lo que no me cierra.
17-02-2015 00:42
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Knofm Sin conexión
Militante
Sin estado :(
***

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 76
Agradecimientos dados: 29
Agradecimientos: 22 en 13 posts
Registro en: May 2011
Mensaje: #4
RE: Patron de diseño "State"
cucho, primero que hay que tomar a los patrones como un modelo, cada uno lo adapta a su necesidad, son un medio y no el fin. Para mi, lo ideal es los cambios de estado los maneje el propio estado. Y si, cuando agregas un nuevo estado vas a tener que modificar aquellos estados que tengan alguna vinculación con el nuevo. Pero el beneficio esta en que esto no altera a la clase contexto (Cuenta en este caso) (y obviamente, tampoco a los estados que no tengan nada que ver).
Por ahí, si en tu implementacion todos los estados pueden realizar transiciones de cualquier a estado a cualquier estado, quizás lo que mas te conviene es llevar el cambio de estado a la clase Cuenta, e implementar un Templated Method para extracción y deposito, y que cada estado extienda el método (abstracto) llamado desde el templated method.
Sobre la modalidad para pasar de un estado a otro, prefiero pasarle con el objeto mismo (this) como argumento, es bastante probable que las clases estado tengan que: o consultarle a la cuenta mas información, o pedirle que modifique algún valor existente.

Saludos y espero haberte ayudado!
17-02-2015 01:00
Envíale un email Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Knofm recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
Virus Sin conexión
Profesor del Modulo A
Programador
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 361
Agradecimientos dados: 37
Agradecimientos: 60 en 46 posts
Registro en: Feb 2012
Mensaje: #5
RE: Patron de diseño "State"
Como te dijeron los patrones no son inmutables o plantillas que siempre se usan igual, enmarcan una idea, que despues llevada a la implementacion puede variar y la forma de implementarlo tiene que ver con el contexto.

Quizas el cambio de los estados en el propio estado o fuera es algo que conviene decidir segun el contexto de que queda mas prolijo, usable y entendible.
17-02-2015 01:10
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Virus recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
Ivanorr1s Sin conexión
Militante
AutoMagically
***

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 93
Agradecimientos dados: 21
Agradecimientos: 65 en 31 posts
Registro en: Jan 2012
Mensaje: #6
RE: Patron de diseño "State"
Hola! Dado que no especificaste si tenias que resolverlo solo usando state, aparezco para dar otro punto de vista.

El problema actual es decidir quién realiza laa transiciones , o bien, quién se encarga de aaber cuando transicionar. Dado que las transiciones dependen de una regla, podríamos aplicar el patrón 'strategy' para obtener una abstracción de la regla a cumplir.

El patrón 'state', como indica el nombre, modela un estado. El estado modifica o altera el comportamiento de un objeto. Entonces, modelamos los estados Silver, Gold, Platinum... etc. Lo ideal seria que el estado no tenga referencias ninguna cuenta puesto que son estados y son superiores al estado interno de cada cuenta. Entonces lo mejor seria pasar como parámetro a la misma cuenta.

Para bajarlo al maravilloso mundo de la programación, definimos:

#Cuenta
>> hacerOperacion (float monto) {
this.estrategiaTransicion.evaluar (this, monto);
this.estado.hacerOperacion (monto);
}

A su vez, cada clase Estado posee su propia variable de clase representando el monto máximo permitido para las operaciones. Y conoce a su siguiente categoría de estado. De esta manera desacoplamos al estado de la transición.

#Silver
>> sgteEstado () {
return new Gold();
}

#Gold
>> sgteEstado () {
return new Platinum ();
}

Ahora la estrategia puede despreocuparse de calcular los intervalos entre estados y, con solo saber el estado de la cuenta y su monto máximo, puede hacer transicionar a la cuenta de un estado a otro.

#EstrategiaCuentas
>> evaluar (Cuenta unaCuenta, float monto) {
if (unaCuenta.getEstado().montoMax() < monto) {
unaCuenta.setEstado (unaCuenta.getEstado().sgteEstado());
}

De esta manera, la solución noa provee de flexibilidad y mantenibilidad, dado que los comportamientos específicos de los estadoa están en sus clases, y el agregado de nuevos estados implica agregar un estado mas al último creado pata que conozca su siguiente.

Esto es pseudocódigo, y es mi humilde punto de vista. Si alguno ve que puede mejorarse o esta mal algo y quiere cambiarlo, bienvenido así respuesta es mas completa!
Espero haber sido de ayuda, y no haber confundido más =)
17-02-2015 01:29
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Ivanorr1s recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
Dios Sin conexión
Presidente del CEIT
.
********

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 1.057
Agradecimientos dados: 32
Agradecimientos: 160 en 132 posts
Registro en: Dec 2011
Mensaje: #7
RE: Patron de diseño "State"
(17-02-2015 00:42)cuchodelosdecadentes escribió:  Pero haciendo algunos ejemplos, veo que si hago esto, si despues quiero agregar un nuevo estado, tengo que modificar cada implementacion de cada clase estado. Es decir, el agregar un nuevo estado me obliga a "abrir" el codigo de cada clase estado para agregar la parte que haria transicionar a ese nuevo estado.

Cualquier cambio de comportamiento en cualquier clase va a generar la necesidad de modificar el código. Pero no es así como decís tampoco: no necesariamente todos los estados van a tener transiciones a todos los otros estados, así que las modificaciones se reducen considerablemente.

Por otro lado, el patrón State para lo que sirve es para cambiar el comportamiento de una clase en tiempo de ejecución. Pero si en el futuro descubrís mil estados distintos más que necesitan sus mil clases estados... es porque fallaste en algo cuando analizabas el problema y la solución, porque lo "normal" sería que un objeto pueda estar en un conjunto finito y no tan variable de estados.

Ivanorr1s en tu solución estás asumiendo que los estados son secuenciales y sólo pueden pasar de uno a otro. En realidad, siguiendo el ejemplo de la cuenta, si le depositás un monto que lo hace pasar a gold hace una transición, y si después venís y retirás MUCHO no tendrías cómo pasar a un estado anterior (por ejemplo: tenías 50k y retirás 45k, debería volver al estado base y no a un "sgte").

«(…)Se arman paquetes… ¿eh?… tecnológicos… tecnológicos portes de… en donde están… este… interrelacionados con las otras capas.(…)»
(Este mensaje fue modificado por última vez en: 17-02-2015 11:24 por Dios.)
17-02-2015 11:15
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] Dios recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
reLlene Sin conexión
Profesor del Modulo A
...
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 307
Agradecimientos dados: 371
Agradecimientos: 63 en 35 posts
Registro en: Aug 2012
Mensaje: #8
RE: Patron de diseño "State"
cuchodelosdecadentes te dejo mi resolución


Archivo(s) adjuntos Imagen(es)
           
25-02-2015 14:02
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] reLlene recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
rodrigo Sin conexión
Profesor del Modulo A
Sin estado :(
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 224
Agradecimientos dados: 57
Agradecimientos: 27 en 17 posts
Registro en: Jul 2008
Mensaje: #9
RE: Patron de diseño "State"
Con respecto a quien hace el cambio de estado mis dos opciones son (deberia ver mejor el problema para evaluar los pros y contras de cada una)

1) usar un factory de estados

this.estado = estadosFactory.getEstado(saldo);

2) que los estados sean inmutables y conozcan el valor de saldo que corresponde a cada nivel (la logica que en el punto 1 estaba en el factory ahora esta en el estado)

// set saldo devuelve siempre un objeto nuevo
this.estado = estado.setSaldo(saldo);


En esta etapa de mi vida (?) creo que iria con la opcion inmutable
25-02-2015 14:39
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
[-] rodrigo recibio 1 Gracias por este post
cuchodelosdecadentes (25-02-2015)
cuchodelosdecadentes Sin conexión
Campeon del cubo Rubik
soooomos los piratas ...
****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 195
Agradecimientos dados: 88
Agradecimientos: 6 en 6 posts
Registro en: Dec 2011
Mensaje: #10
RE: Patron de diseño "State"
claro, el tema para mi sigue siendo esa premisa de "closed for modification" a la que veo que permanentemente hay que contradecirla.
mas en un caso como este. suponiendo que podes hacer depositos y extracciones sin limites, entonces desde cualquier estado podes pasar a cualquiera sin escalas. o sea, el grafo de estados es todo contra todos. y entonces, agregar un nuevo estado significa modificar todos los anteriores.
pero que se yo, no es mi idea contradecir a ningun patron. simplemente, que hay cosas que me hacen dudar.

otra cosa que me hace ruido es en ejemplos como el de tamagotchi, donde dependiendo del estado en el que este, tiene mas o menos atributos. yo entiendo que se modelan en cada estado, pero no me cierra porque conceptualmente los atributos son caracteristicas del objeto/clase y no de un colaborador en este caso.



pero bueno... que se yo.

otra cosa, fijense que a veces la clase contexto tiene que exponer un mensaje "pasarA: unEstado" ( o algo por el estilo).
entonces que sentido tiene enloquecerte haciendo un diagrama de estados ( hablo de una aplicacion real, con mucho estados, obviamanete no para este ej simple) si despues "cualquier gil" que haga de cliente le puede mandar el mensaje pasarA ?
ojo, entiendo que en lenguajes como java y demas, tenemos lo de visibilidad y demas yerbas pero asi y todo.... no se. no me suena.

lo que quise decir, es que conceptualmente ( por lo menos para mi), un objeto deberia transicionar de un estado a otro como consecuencia de un evento ( como podria ser extraer o depositar en este caso), y no porque alguien especificamente se lo solicite ( a traves del metodo pasarA: unEstado).
(Este mensaje fue modificado por última vez en: 25-02-2015 15:06 por cuchodelosdecadentes.)
25-02-2015 14:58
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
rodrigo Sin conexión
Profesor del Modulo A
Sin estado :(
*****

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 224
Agradecimientos dados: 57
Agradecimientos: 27 en 17 posts
Registro en: Jul 2008
Mensaje: #11
RE: Patron de diseño "State"
Estoy de acuerdo, los metodos como el "pasarA" personalmente no me gustan, el 99% de las veces estan encubriendo la necesidad de un value object, haciendolo asi el diseño queda limpio



class Cuenta {

function depositar(monto) {
this.saldo += monto;
this.estado = this.estado.setSaldo(this.saldo);
}

}

// ejemplos de uso
estado = new Estado(); // normal
estado = estado.setSaldo(22k); // ahora es silver
estado = estado.setSaldo(55k); // ahora es gold




La cuenta no necesita exponer nada y el estado se actualiza automaticamente
25-02-2015 15:34
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Ivanorr1s Sin conexión
Militante
AutoMagically
***

Ing. en Sistemas
Facultad Regional Buenos Aires

Mensajes: 93
Agradecimientos dados: 21
Agradecimientos: 65 en 31 posts
Registro en: Jan 2012
Mensaje: #12
RE: Patron de diseño "State"
Otra opción sería utilizar el patrón Observer (sería complejizar la solución, pero ganamos en abstracción), dado que hay un evento en el cual la cuenta puede (o no) cambiar de estado. Entonces, cada vez que se deposite / extraiga dinero de la cuenta (es decir, que ocurriese una variación en el saldo), se notifica a un ¿sistemaDeCuentas?, el cual determinará el estado de la cuenta a partir de la variación en el saldo. De esta manera, la cuenta sólo se preocupa de saber extraer / depositar saldo, y no tiene la responsabilidad de estar verificando su estado, sino que notifica a quien debe de la operación, y este 'observador' se encarga de hacer lo que tenga que hacer. Bajando a código:

#SistemaDeCuentas (Observer de Cuenta)
>> notificarVariacionDeSaldoDe(Cuenta unaCuenta) {
if(unaCuenta.getSaldo() > 20000 && unaCuenta.getSaldo() < 50000) {
unaCuenta.setEstado(new Silver());
} else if (unaCuenta.getSaldo() >= 50000) {
unaCuenta.setEstado(new Gold());
}
}

De todos modos, odio usar 'ifs'. Me suena que es un error de análisis del sistema, es decir, si una cuenta va a cambiar su comportamiento TAN rápidamente dado que depende del saldo, creo que esta opción es bastante flexible para admitir cambios de números de saldo, o bien, agregado de nuevos estados. PERO, si en un futuro el estado de una cuenta dependiese de otra condición adicional (como podría ser la antigüedad, por ejemplo) esta solución ya no es muy linda. (igual, peco de hacer futurología en esta última opción).
25-02-2015 16:15
Encuentra todos sus mensajes Agregar agradecimiento Cita este mensaje en tu respuesta
Buscar en el tema
Enviar respuesta 




Usuario(s) navegando en este tema: 1 invitado(s)