ventajas strategy patrones patron observer entre diseño diferencia desventajas comportamiento java design-patterns automata state-machine

java - strategy - patrones de comportamiento c#



Problema de patrón de diseño que involucra N estados y transiciones entre ellos (6)

¿No funcionará el patrón de estado ?

Tengo un problema a la mano y no consigo el patrón de diseño que debo utilizar. El problema va como tal:

Tengo que construir un sistema que tenga estados ''N'' y mi sistema tiene que hacer una transición de cualquier estado a cualquier otro estado dependiendo de algunas condiciones. Ej: en condición 1, movimiento del estado 1 a 3 y en condición 2 del estado 1 a 4.

Incluso la transición de un estado a otro puede realizarse en 2 o más condiciones diferentes.

Por ejemplo, la transición del estado 1 al estado 3 se puede hacer cuando:
condición 1: "es un domingo"
condición 2: "Está lloviendo"
condición 3: "Está lloviendo y el domingo"
En cada condición, el procesamiento en el Estado 3 puede ser diferente.

Espero haber podido entender el problema de manera legible. Por favor ayuda

Muchas gracias


Como han dicho otros, una máquina de estados puede modelarse en un código de procedimiento con un interruptor o en un código OO con el patrón de estado, que es probablemente lo que estaba buscando.

Sin embargo, una tercera forma es codificarlo como un gráfico, con estados como nodos y condiciones como bordes dirigidos. El patrón de visitante se puede usar para aplicar el gráfico a diferentes usos. esto se prestaría particularmente bien para diseños donde los estados y / o las transiciones podrían ser definidos por el usuario, pero probablemente requerirían más memoria que las máquinas de estado codificadas en hardware descritas en las otras respuestas.


El patrón de diseño del estado trabaja en el concepto de cambio de estado. Todo el ciclo de vida del proceso se puede dividir en varias fases. Con la finalización de cada fase, el proceso sale de un estado y entra en otro estado.

Por ejemplo, en el marco JSF, el ciclo de vida completo de respuesta de solicitud web se divide en seis fases:

Después de completar cada proceso de fase sale de un estado y entra en otro estado. Por ejemplo, después de RestoreValuePhase podemos decir ViewRestored como estado de salida y RequestApply como estado de entrada.

Por lo tanto, para implementar el patrón de diseño del estado Es necesario dividir todo el proceso de tal manera que se pueda procesar en varias fases con cada salida de fase que define un cambio de estado.

Ahora entendamos esto con el siguiente código.

Cualquier ciclo de vida del proyecto se puede dividir en múltiples fases como

requirementAssessment Design Development QualityAssessment Deploy Closure

Así que estas son las fases utilizadas en el siguiente ejemplo.

Reglas :

  1. Necesitamos definir una clase donde podamos almacenar el estado actual del proceso. La clase NextPhase en el código de abajo está haciendo eso.

  2. Necesitamos definir una Interfaz en la que podamos proporcionar el método de contacto que se implementaría en cada fase. En el siguiente código, ProjectPhase está haciendo eso.

Obtenga más información sobre el patrón de diseño de estado aquí - Patrón de diseño de estado

http://efectivejava.blogspot.in/2013/09/java-state-design-patten-oops-state.html?utm_source=BP_recent


Es claramente un caso de una máquina de estado finito, pero es mejor combinar las condiciones en lugar de crear una nueva condición para cada combinación. No me gustó el ejemplo de Java para el patrón de estado en Wikipedia, ya que los estados conocen otros estados que no tendrían sentido en muchos escenarios. Una tabla de transición que mantiene un registro del estado, las condiciones aplicables y el estado, ayuda a resolver ese problema.

Mis dos centavos para una máquina de estados finitos orientada a objetos. Hay mejoras que podrías hacer en el frente de OO, pero te da la idea.

class Transition { State from; Set<Condition> conditions; State to; } class State { String state; } class Condition { String condition; }

La máquina de estado se puede construir con los tipos anteriores. No hay comprobación de errores, pero puede lanzar una excepción o algo si no se encuentra el siguiente estado para algunas condiciones.

class StateMachine { List<Transition> transitions; State current; StateMachine(State start, List<Transition> transitions) { this.current = start; this.transitions = transitions; } void apply(Set<Condition> conditions) { current = getNextState(conditions); } State getNextState(Set<Condition> conditions) { for(Transition transition : transitions) { boolean currentStateMatches = transition.from.equals(current); boolean conditionsMatch = transition.conditions.equals(conditions); if(currentStateMatches && conditionsMatch) { return transition.to; } } return null; } }

Y una prueba de ejecución:

Edición : Con algunas transiciones más y nuevos estados basados ​​en tu comentario:

State one = new State("one"); State two = new State("two"); State three = new State("three"); Condition sunday = new Condition("Sunday"); Condition raining = new Condition("Raining"); Condition notSunday = new Condition("Not Sunday"); Condition notRaining = new Condition("Not Raining"); List<Transition> transitions = new ArrayList<Transition>(); transitions.add(one, new Set(sunday), three); transitions.add(one, new Set(sunday), two); // <<--- Invalid, cant go to two and three transitions.add(one, new Set(raining), three); transitions.add(one, new Set(sunday, raining), three); transitions.add(one, new Set(notSunday, notRaining), three); StateMachine machine = new StateMachine(one, transitions); System.out.print(machine.current); // "one" machine.apply(new Set(sunday, raining)); System.out.print(machine.current); // "three

Tuve una experiencia amarga con el uso de una máquina de estados para un proyecto bastante grande. El problema era con los estados compuestos. Al igual que la condición compuesta que mencionaste (domingo y lloviendo), técnicamente podría haber estados compuestos que podrían dividirse en estados unitarios. Este puede o no ser el caso en su situación, pero vale la pena mencionarlo. Si ese es el caso, es mejor modificar la máquina de estados finitos clásica y usar un conjunto de estados en lugar de un solo estado para representar los estados desde y hacia. Si su N es grande, esto ayudará a mantener intactos los niveles de cordura. Piense en las carpetas de hotmail frente a las etiquetas de gmail. La tabla de transición se presentaría como

Transition(Set<State> from, Set<Condition> conditions, Set<State> to)


Esto suena como el uso típico de una máquina de estados finitos.

en resumen, la máquina de estados describe los diversos estados en los que puede estar su sistema y bajo qué condiciones puede ir de estado a estado. Una máquina de estados se describe exactamente como su descripción en inglés. Y se puede describir formalmente usando diagramas de estado.

En código podrías hacer una máquina de estados como esta:

enum State { Init, ShowMenu, ShowMsg, DisplayVideo, Exit }; State state = State.Init; while (state != State.Exit) { switch(state) { case State.Init: init(); state = State.ShowMenu; break; case State.ShowMenu: if(lastMenuItemSelected==1) state = State.ShowMsg; if(lastMenuItemSelected==2) state = State.DisplayVideo; break; case State.ShowMsg: .... break; .... }

No estoy seguro si obtuve la sintaxis exacta correcta para Java ... Estoy más interesado en C #


Lo primero que noté sobre su ejemplo fue que el Estado 3 = (Estado 1 == verdadero && Estado 2 == verdadero). Esto no se escalará muy bien a medida que se involucren más estados posibles. Si solo está considerando si está lloviendo o si es domingo, puede tener una enumeración como esta, con 4 tipos posibles:

enum State { CLEAR_OTHER_DAY, RAINING_OTHER_DAY, CLEAR_SUNDAY, RAINING_SUNDAY }

Esto le permitiría establecer las condiciones de forma limpia en un bloque de conmutación cuando sea el momento de codificar. Pero si también debe considerar si hace calor en el exterior, debe agregar 4 valores más a esa enumeración para capturar todas las condiciones posibles. Y más adelante en su proyecto, su código puede necesitar capturar más condiciones de las que actualmente prevé.

En cuanto a un patrón de diseño, el patrón de estado y su ejemplo de Java en Wikipedia parecen ser un buen lugar para comenzar.

El ejemplo de Wikipedia tiene una clase StateContext con un método llamado setState que toma un nombre. Pensé en sugerirle que agregue la lógica de determinación de estado aquí, pero eso haría que su clase StateContext tenga que acercarse demasiado a los detalles de implementación de sus otras clases. Sería mejor poner un método para determinar el estado del sistema en una clase que conozca fácilmente las condiciones para pasar de un estado a otro. De esta manera, si su proyecto necesita cambiar en el futuro y usted tiene más estados para realizar un seguimiento o diferentes condiciones, solo necesita mantener la lógica en un lugar.