Intención del patrón
- Permitir a un objeto cambiar su comportamiento cuando cambia su estado interno. El objeto parecerá cambiar su clase.
- Un estado orientado a objetos.
- Un Wrapper + el objeto envuelto por el Wrapper + colaboración.
Ejemplo de problema
El comportamiento de un objeto monolítico y debe cambiar su comportamiento en tiempo de ejecución según su estado. O bien, una aplicación que se caracteriza por tener extensos y numerosos sentencias case que manejan el control de flujo basado en el estado de la aplicación.Discusión
El patrón State es una solución al problema de cómo hacer que el comportamiento dependa del estado.- Definir una clase "Context" para presentar una única interfaz al mundo exterior.
- Definir una clase base abstracta: State.
- Representar los diferentes estados como clases derivadas de la clase base State.
- Definir comportamientos específicos para un estado en las clases apropiadas derivadas de State.
- Mantener un puntero al "estado" actual en la clase de "contexto".
- Para cambiar el estado, cambiar el punto del "estado" actual.
Un enfoque basado en tablas para diseñar un una cantidad finita de estado, realiza un buen trabajo de especificación de transiciones de estado, pero resulta difícil agregar acciones para acompañar las transiciones de estado. El enfoque basado en el patrón usa código (en lugar de estructuras de datos) para especificar las transiciones de estado, pero realiza un buen trabajo al acomodar las acciones de transiciones de estado.
Estructura
La interfaz de estado es encapsulada en la clase "wrapper". La jerarquía de interfaz del objeto State refleja la interfaz del wrapper con la excepción de un parámetro adicional. Éste argumento permite a las clases derivadas envueltas por el wrapper llamar nuevamente a éste como sea necesario. La complejidad, que de otra manera oscurecería la lógica de la clase wrapper, está perfectamente compartimentada y encapsulada en una jerarquía polimórfica, hacia la cual el objeto wrapper delega.Ejemplo
El patrón State permite a un objeto cambiar su comportamiento cuando su estado interno cambia. Este patrón puede ser observado en una máquina expendedora. Éstas máquinas tienen estados basados en el stock, cantidad de dinero depositado, la habilidad de dar el vuelto, el ítem seleccionado, etc. Cuando el dinero es depositado y la selección está hecho, la máquina puede realizar la entrega del producto y no dar vuelto, entregar el producto y dar vuelto o no entregar el producto debido a que está agotado.Check list
- Identificar una clase existente o crear una nueva clase, que servirá como "estado" desde la perspectiva del cliente. Esta clase es el wrapper.
- Crear una clase base State que replique los métodos de la interfaz de estado. Cada método toma un argumento adicional: una instancia de la clase wrapper. La clase base State especifica cualquier comportamiento por defecto que sea "útil".
- Crear una clase derivada de State por cada dominio de estado. Dichas clases derivadas sólo sobrescriben los métodos que necesitan.
- La clase wrapper mantiene un objeto que representa el estado "actual".
- Todas las solicitudes de los clientes al wrapper son simplemente delegadas al objeto State actual y es pasado el puntero a este objeto wrapper.
- Los métodos de State cambian el estado "actual" en el objeto wrapper según corresponda.
Reglas prácticas
- Los objetos State a menudo son Singleton.
- El patrón Flyweight explica cuándo y cómo los objetos State pueden ser compartidos.
- El patrón Interpreter puede usa a State para definir contextos de análisis.
- El patrón Strategy tiene dos diferentes implementaciones. La primera es similar a State. La diferencia está en tiempo de enlace (Strategy es un patrón que se enlaza una vez, mientras que State es más dinámico).
- La estructura de StateI y Bridge son idénticas (excepto que Bridge admite jerarquí de clases, mientras que State sólo una). Los dos patrones utilizan la misma estructura para resolver diferentes problemas: State le permite a un objeto cambiar su comportamiento en base a su estado, mientras que la intención de Bridge es desacoplar una abstracción de su implementación para que ambas puedan variar independientemente.
- La implementación del patrón State se construye sobre el patrón Strategy. La diferencia entre ambos es la intención. Con Strategy, la elección de algoritmo es bastante estable. Con State, un cambio en el estado del objeto Context causa que se seleccione a partir de su paleta de objetos Strategy.
Ejemplo de código en C#
using System;
class MainApp
{
static void Main()
{
// Setup context in a state
Context c = new Context(new ConcreteStateA());
// Issue requests, which toggles state
c.Request();
c.Request();
c.Request();
c.Request();
// Wait for user
Console.Read();
}
}
// "State"
abstract class State
{
public abstract void Handle(Context context);
}
// "ConcreteStateA"
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
// "ConcreteStateB"
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
// "Context"
class Context
{
private State state;
// Constructor
public Context(State state)
{
this.State = state;
}
// Property
public State State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State: " +
state.GetType().Name);
}
}
public void Request()
{
state.Handle(this);
}
}
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA
2 comentarios:
MUY BUENO, gracias.
Me alegra que te haya gustado.
Publicar un comentario
Muchas gracias por leer el post y comentarlo.