Estado (patrón de diseño)

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 25 de marzo de 2014; las comprobaciones requieren 20 ediciones .
Estado
Estado
Tipo de conductual
Descrito en Patrones de diseño

State ( Eng.  State ) es un patrón de diseño de comportamiento . Se utiliza en aquellos casos en que, durante la ejecución del programa, el objeto debe cambiar su comportamiento en función de su estado.

El patrón consta de 3 bloques:

Widget es una clase cuyos objetos deberían cambiar su comportamiento dependiendo del estado.

IState es una interfaz que cada uno de los estados concretos debe implementar. A través de esta interfaz, el objeto Widget interactúa con el estado delegándole llamadas a métodos. La interfaz debe contener medios para la retroalimentación al objeto cuyo comportamiento se va a cambiar. Para ello se utiliza un evento ( patrón Publisher - Subscriber ). Esto es necesario para reemplazar el objeto de estado durante la ejecución del programa cuando ocurren eventos. Puede haber ocasiones en las que el propio Widget sondee periódicamente el objeto de estado en busca de una transición.

StateA ... StateZ - clases de estados concretos. Debe contener información sobre en qué condiciones y en qué estados el objeto puede pasar del estado actual. Por ejemplo, un objeto puede ir del Estado A al Estado B y al Estado C, y del Estado B al Estado A, y así sucesivamente. El objeto de uno de ellos debe contener el Widget cuando se crea.

La aplicación de este patrón puede ser difícil si los estados necesitan comunicarse o si un estado establece las propiedades de otro. En este caso, necesitará un objeto global, que no es una solución arquitectónica muy buena.

Ejemplos

Ejemplo de C++

Texto fuente en C++ #pragma una vez #incluir <cadena> #incluir <iostream> clase Estado ; clase EstadoContexto ; clase estado solido ; clase LiquidState ; clase GasState ; estado de clase { std :: nombre de cadena ; _ público : Estado ( const std :: cadena y nombre ) : nombre ( nombre ) {} std :: cadena ObtenerNombre () { devolver nombre ; } Congelación de vacío virtual ( StateContext * ) = 0 ; calor vacío virtual ( StateContext * ) = 0 ; }; clase EstadoContexto { privado : Estado * estado ; público : StateContext ( Estado * estado ) : estado ( estado ) {} congelación vacía () { std :: cout << "Congelando " << estado -> GetName () << "..." << std :: endl ; estado -> Congelar ( esto ); } CalorVacío ( ) { std :: cout << "Calefacción " << estado -> GetName () << "..." << std :: endl ; estado -> Calor ( este ); } void SetState ( Estado * s ) { std :: cout << "Cambiando estado de " << estado -> GetName () << " a " << s -> GetName () << "..." << std :: endl ; borrar estado ; estado = s ; } Estado * ObtenerEstado () { estado de retorno ; } ~ EstadoContexto () { borrar estado ; } }; clase SolidState : estado público { público : SolidState () : Estado ( "Sólido" ) {} Congelación de vacío virtual ( StateContext * state ); calor vacío virtual ( StateContext * state ); }; clase LiquidState : estado público { público : LiquidState () : Estado ( "Líquido" ) {} Congelación de vacío virtual ( StateContext * state ); calor vacío virtual ( StateContext * state ); }; clase GasState : estado público { público : GasState () : Estado ( "Gas" ) {} Congelación de vacío virtual ( StateContext * state ); calor vacío virtual ( StateContext * state ); }; void SolidState::Freeze ( StateContext * estado ) { std :: cout << "No pasa nada" << std :: endl ; } void SolidState::Heat ( StateContext * estado ) { estado -> SetState ( nuevo LiquidState ()); } void LiquidState::Freeze ( StateContext * estado ) { estado -> SetState ( nuevo SolidState ()); } void LiquidState::Heat ( ContextoEstado * estado ) { estado -> SetState ( nuevo GasState ()); } void GasState::Freeze ( ContextoEstado * estado ) { estado -> SetState ( nuevo LiquidState ()); } void GasState::Heat ( ContextoEstado * estado ) { std :: cout << "No pasa nada" << std :: endl ; } prueba nula () { StateContext * sc = new StateContext ( new SolidState ()); sc -> Calor (); sc -> Calor (); sc -> Calor (); sc -> congelar (); sc -> congelar (); sc -> congelar (); eliminar sc ; }

Ejemplo en C#

Aplicar una plantilla

Texto fuente en C# utilizando el sistema ; espacio de nombres Digital_Patterns.Behavioral.State { interfaz pública IAutomatState { String GotApplication (); Aplicación de Verificación de Cadenas ( ); String AlquilerApartamento (); CadenaDispensarClaves ( ); } interfaz pública IAutomat { void GotApplication (); void CheckApplication (); void AlquilerApartamento (); void SetState ( IAutomateState s ); IAutomateState GetWaitingState (); IAutomatState GetGotApplicationState (); IAutomatState GetApartmentRentedState (); IAutomatState GetFullyRentedState (); Int32 Cuenta { obtener ; conjunto ; } } Automat de clase pública : IAutomat { private IAutomatState _waitingState ; privado IAutomatState _gotApplicationState ; privado IAutomatState _apartmentRentedState ; privado IAutomatState _fullyRentedState ; privado IAutomatState _estado ; privado Int32_count ; _ Autómata público ( Int32 n ) { _count = n ; _waitingState = new WaitingState ( este ); _gotApplicationState = nuevo GotApplicationState ( este ); _apartmentRentedState = nuevo ApartmentRentedState ( este ); _fullyRentedState = new FullyRentedState ( este ); _estado = _estadoEsperando ; } public void GotApplication () { Consola . WriteLine ( _state.GotApplication ( ) ); } public void CheckApplication () { Consola . WriteLine ( _state.CheckApplication ( ) ); } public void RentApartment () { Consola . WriteLine ( _state.RentApartment ( ) ); consola _ WriteLine ( _state . DispenseKeys ()); } public void SetState ( IAutomateState s ) { _state = s ; } public IAutomatState GetWaitingState () { return _waitingState ; } public IAutomatState GetGotApplicationState () { return _gotApplicationState ; } public IAutomatState GetApartmentRentedState () { return _apartmentRentedState ; } public IAutomatState GetFullyRentedState () { return _fullyRentedState ; } public int Count { obtener { return _count ; } establecer { _contar = valor ; } } } clase pública WaitingState : IAutomatState { private Automat _automat ; public WaitingState ( Automat automat ) { _automat = automat ; } Public String GotApplication () { _automat . SetState ( _automat . GetGotApplicationState ()); volver "Gracias por la solicitud". ; } public String CheckApplication () { return "Tienes que enviar una solicitud". ; } public String RentApartment () { return "Tienes que enviar una solicitud". ; } public String DispenseKeys () { return "Tienes que enviar una solicitud". ; } } clase pública GotApplicationState : IAutomatState { private Automat _automat ; privado solo lectura Random _random ; public GotApplicationState ( Automat automat ) { _automat = automat ; _random = new Random ( System . DateTime . Now . Millisecond ); } public String GotApplication () { return "Ya recibimos su solicitud". ; } public String CheckApplication () { var yesNo = _random . Siguiente () % 10 ; if ( yesNo > 4 && _automat . Count > 0 ) { _automat . SetState ( _automat . GetApartmentRentedState ()); return "Felicitaciones, fuiste aprobado". ; } más { _automático . SetState ( _automat . GetWaitingState ()); return "Lo siento, no fue aprobado". ; } } public String RentApartment () { return "Debe verificar su solicitud". ; } public String DispenseKeys () { return "Debe verificar su solicitud". ; } } public class ApartmentRentedState : IAutomatState { private Automat _automat ; public ApartmentRentedState ( Automat automat ) { _automat = automat ; } public String GotApplication () { return "Espera, te estamos alquilando un apartamento". ; } public String CheckApplication () { return "Espera, te estamos alquilando un apartamento". ; } public String RentApartment () { _automat . Contar = _automat . Cuenta - 1 ; return "Te alquilo un apartamento...." ; } public String DispenseKeys () { if ( _automat . Count <= 0 ) _automat . SetState ( _automat . GetFullyRentedState ()); más _automático . SetState ( _automat . GetWaitingState ()); volver "¡Aquí están tus llaves!" ; } } public class FullyRentedState : IAutomatState { private Automat _automat ; public FullyRentedState ( Automat automat ) { _automat = automat ; } public String GotApplication () { return "Lo sentimos, estamos totalmente alquilados". ; } public String CheckApplication () { return "Lo sentimos, estamos totalmente alquilados". ; } public String RentApartment () { return "Lo sentimos, estamos totalmente alquilados". ; } public String DispenseKeys () { return "Lo sentimos, estamos completamente alquilados". ; } } programa de clase { static void Main ( cadena [] args ) { var automat = new Automat ( 9 ); autómata _ TengoAplicación (); autómata _ VerificarAplicación (); autómata _ AlquilerApartamento (); } } }

El mismo ejemplo, sin aplicar la plantilla.

Texto fuente en C# utilizando el sistema ; espacio de nombres Digital_Patterns.Behavioral.State { public enum State { FULLY_RENTED = 0 , WAITING = 1 , GOT_APPLICATION = 2 , APARTMENT_RENTED = 3 , } public class RentalMethods { private readonly Random _random ; privado Int32 _númeroApartamentos ; Estado privado _estado = Estado . ESPERANDO ; Public RentalMethods ( Int32 n ) { _numberApartments = n ; _random = new Random ( System . DateTime . Now . Millisecond ); } public void GetApplication () { switch ( _state ) { estado del caso . FULLY_RENTED : Consola . WriteLine ( "Lo siento, estamos totalmente alquilados" ); romper ; Estado del caso . ESPERANDO : _estado = Estado . GOT_APLICACION ; consola _ WriteLine ( "Gracias por la aplicación" ); romper ; Estado del caso . GOT_APPLICATION : Consola . WriteLine ( "Ya recibimos su solicitud" ); romper ; Estado del caso . APARTAMENTO_RENTADO : Consola . WriteLine ( "Espera, te estamos alquilando un apartamento" ); romper ; } } public void CheckApplication () { var yesNo = _random . siguiente ()% 10 ; interruptor ( _estado ) { caso Estado . FULLY_RENTED : Consola . WriteLine ( "Lo siento, estamos totalmente alquilados" ); romper ; Estado del caso . ESPERANDO : Consola . WriteLine ( "Tienes que enviar una solicitud" ); romper ; Estado del caso . GOT_APPLICATION : if ( yesNo > 4 && _numberApartments > 0 ) { Console . WriteLine ( "Felicitaciones, fue aprobado" ); _estado = Estado . APARTAMENTO_RENTADO ; AlquilerApartamento (); } más { Consola . WriteLine ( "Lo siento, no fue aprobado" ); _estado = Estado . ESPERANDO ; } romper ; Estado del caso . APARTAMENTO_RENTADO : Consola . WriteLine ( "Espera, te estamos alquilando un apartamento" ); romper ; } } public void RentApartment () { switch ( _state ) { case State . FULLY_RENTED : Consola . WriteLine ( "Lo siento, estamos totalmente alquilados" ); romper ; Estado del caso . ESPERANDO : Consola . WriteLine ( "Tienes que enviar una solicitud" ); romper ; Estado del caso . GOT_APPLICATION : Consola . WriteLine ( "Debe tener su aplicación revisada" ); romper ; Estado del caso . APARTAMENTO_RENTADO : Consola . WriteLine ( "Te alquilo un apartamento...." ); _númeroApartamentos --; DispenseKeys (); romper ; } } public void DispenseKeys () { switch ( _state ) { case State . FULLY_RENTED : Consola . WriteLine ( "Lo siento, estamos completamente alquilados" ); romper ; Estado del caso . ESPERANDO : Consola . WriteLine ( "Tienes que enviar una solicitud" ); romper ; Estado del caso . GOT_APPLICATION : Consola . WriteLine ( "Debe tener su aplicación revisada" ); romper ; Estado del caso . APARTAMENTO_RENTADO : Consola . WriteLine ( "¡Aquí están tus llaves!" ); _estado = Estado . ESPERANDO ; romper ; } } } class Program { static void Main ( string [] args ) { var rentalMethods = new RentalMethods ( 9 ); métodos de alquiler . ObtenerAplicación (); métodos de alquiler . VerificarAplicación (); métodos de alquiler . AlquilerApartamento (); métodos de alquiler . DispenseKeys (); } } }

Ejemplo de Java

Fuente Java ejemplo de estado de clase pública { public static void main ( String [] args ) { StateContext context = new StateContext (); contexto _ calor (); contexto _ calor (); contexto _ calor (); contexto _ congelar (); contexto _ congelar (); contexto _ congelar (); // SALIDA: // Calentamiento de sustancia sólida... // Cambio de estado a líquido... // Calentamiento de sustancia líquida... // Cambio de estado a gaseoso... // Calentamiento de sustancia gaseosa... // No pasa nada . // Congelando sustancia gaseosa... // Cambiando de estado a líquido... // Congelando sustancia líquida... // Cambiando de estado a sólido... // Congelando sustancia sólida... // No pasa nada. } } Estado de la interfaz { String getName (); congelación vacía ( contexto StateContext ); calor vacío ( contexto StateContext ); } clase SolidState implementa Estado { Cadena final estática privada NOMBRE = "sólido" ; public String getName () { return NOMBRE ; } congelación de vacío público ( contexto StateContext ) { System . fuera _ println ( "No pasa nada" ); } public void heat ( contexto StateContext ) { contexto . setState ( nuevo LiquidState ()); } } clase LiquidState implementa Estado { Cadena final estática privada NOMBRE = "líquido" ; public String getName () { return NOMBRE ; } congelación de vacío público ( contexto StateContext ) { contexto . setState ( nuevoEstadoSolido ( )); } public void heat ( contexto StateContext ) { contexto . setState ( nuevo estado gaseoso ()); } } class GaseousState implementa Estado { Cadena final estática privada NOMBRE = "gaseoso" ; public String getName () { return NOMBRE ; } congelación de vacío público ( contexto StateContext ) { contexto . setState ( nuevo LiquidState ()); } public void heat ( contexto StateContext ) { System . fuera _ println ( "No pasa nada" ); } } clase EstadoContexto { estado de estado privado = nuevo SolidState (); congelación de vacío público () { System . fuera _ println ( "Congelando" + estado . getNombre () + "sustancia..." ); estado _ congelar ( esto ); } public void heat () { System . fuera _ println ( "Calefacción" + estado . getNombre () + "sustancia..." ); estado _ calor ( esto ); } public void setState ( Estado estado ) { System . fuera _ println ( "Cambiando de estado a" + estado . getNombre () + "..." ); esto _ estado = estado ; } estado público getState () { return state ; } }

Ejemplo de Python

Código fuente en Python de abc import ABCMeta , método abstracto Estado de la clase ( metaclase = ABCMeta ): @abstractmethod def comer ( auto ) -> str : pasar @abstractmethod def find_food ( self ) -> str : pasar @abstractmethod def mover ( auto ) -> str : pasar @abstractmethod def sueño ( auto ) -> str : pasar clase SleepState ( Estado ): def comer ( self ) -> str : return 'no puedo comer mientras duermo' def find_food ( self ) -> str : return 'encuentra comida, pero solo en sus sueños' def move ( self ) -> str : return 'no puedo moverme mientras duermo' def dream ( self ) -> str : return 'dormir y tener un sueño maravilloso' clase OnGroundState ( Estado ): def eat ( self ) -> str : return 'arroja las almejas recolectadas en el vientre y comienza a comerlas lentamente' def find_food ( self ) -> str : return 'encuentra el cadáver maloliente pero comestible de una ballena varada' def move ( self ) -> str : return 'se arrastra torpemente a lo largo de la costa' def dream ( self ) -> str : return 'se detiene por un momento, soñando con una mujer familiar' clase InWaterState ( Estado ): def comer ( self ) -> str : return 'no puedo comer en el agua' def find_food ( self ) -> str : return 'arar el fondo del mar con colmillos, atrapar almejas con sus vibrisas' def move ( self ) -> str : return 'corta con gracia las olas de los océanos del mundo' def dream ( self ) -> str : return 'no duermas ni sueñes en el agua - eso es demasiado difícil' clase morsa : def __init__ ( self , estado : Estado ) -> Ninguno : self . _estado = estado def change_state ( self , state : State ) -> Ninguno : self . _estado = estado def comer ( auto ) -> Ninguno : auto . _ejecutar ( 'comer' ) def find_food ( self ) -> Ninguno : self . _ejecutar ( 'buscar_comida' ) def move ( self ) -> Ninguno : self . _ejecutar ( 'mover' ) def dream ( self ) -> Ninguno : self . _ejecutar ( 'sueño' ) def _execute ( self , operación : str ) -> Ninguno : prueba : func = getattr ( self . _state , operación ) print ( 'Morsa {} .' . format ( func ())) excepto AttributeError : print ( 'Morsa haciendo esto no puedo.' ) if __name__ == '__main__' : dormir = SleepState () on_ground = OnGroundState () in_water = InWaterState () morsa = Morsa ( on_ground ) print ( 'OUTPUT:' ) morsa . change_state ( in_water ) morsa . mover () morsa . find_food () morsa . change_state ( on_ground ) morsa . comer () morsa . mover () morsa . sueño () morsa . change_state ( dormir ) morsa . sueño () ''' SALIDA: Morsa corta con gracia a través de las olas de los océanos. La morsa ara el fondo del mar con sus colmillos, atrapando moluscos con sus vibrisas. La morsa vuelca los moluscos extraídos en el vientre y comienza a comerlos lentamente. La morsa se arrastra torpemente por la costa. La morsa se detiene por un momento, soñando con una hembra familiar. La morsa duerme y ve un sueño maravilloso. '''

Ejemplo de Javascript

Un ejemplo con estados cambiantes de State.

Texto fuente en javascript // Estado de la "interfaz" función Estado () { esto . algúnMetodo = función () { }; esto _ estado siguiente = función () { }; } // implementación del estado // función de primer estado StateA ( widjet ) { var duplicate = this ; // referencia al objeto instanciado (porque esto puede cambiar) esto _ algunMetodo = function () { alerta ( "StateA.someMethod" ); duplicar _ estado siguiente (); }; esto _ nextState = function () { alert ( "StateA > StateB" ); artilugio _ onNextState ( nuevo EstadoB ( widjet ) ); }; } EstadoA . prototipo = nuevo estado (); Estado A. prototipo _ constructor = EstadoA ; // segunda función de estado StateB ( widjet ) { var duplicate = this ; esto _ algunMetodo = function () { alerta ( "StateB.someMethod" ); duplicar _ estado siguiente (); }; esto _ nextState = function () { alert ( "StateB > StateA" ); artilugio _ onNextState ( nuevo EstadoA ( widjet ) ); }; } EstadoB . prototipo = nuevo estado (); EstadoB . prototipo _ constructor = EstadoB ; // Widget "interfaz" Widget de función () { esto . algúnMetodo = función () { }; esto _ onNextState = función ( estado ) { }; } // Implementación de widgets function Widget1 () { var state = new StateA ( este ); esto _ algúnMetodo = función () { estado . algúnMetodo (); }; esto _ onNextState = function ( newState ) { state = newState ; }; } Widget1 . prototipo = nuevo Widget (); Widget1 . prototipo _ constructor = Widget1 ; // uso var widget = nuevo Widget1 (); artilugio _ algúnMetodo (); // EstadoA.algúnMétodo // EstadoA > Widget EstadoB . algúnMetodo (); // EstadoB.algunMetodo // EstadoB > EstadoA

Cambiar estados llamando a un método en el Widget (de la versión en inglés del artículo).

Texto fuente en javascript // Estado de la "interfaz" función AbstractTool () { esto . moveTo = función ( x , y ) { }; esto _ mouseDown = función ( x , y ) { }; esto _ ratón arriba = función ( x , y ) { }; } // implementación del estado // función de herramienta de lápiz PenTool ( widjet ) { var duplicate = this ; // referencia al objeto instanciado (porque esto puede cambiar) var mouseIsDown = false ; // el botón del mouse no está presionado actualmente var lastCoords = []; // coordenadas pasadas del cursor del mouse esto _ moveTo = function ( x , y ) { if ( mouseIsDown && lastCoords . length ) { drawLine ( lastCoords , [ x , y ]); } ultimasCoords = [ x , y ]; }; esto _ mouseDown = function ( x , y ) { mouseIsDown = true ; últimasCoords = [ x , y ]; }; esto _ mouseUp = function ( x , y ) { mouseIsDown = false ; }; function dibujarLínea ( coords1 , coords2 ) { alerta ( " dibujarLínea: [" + coords1 [ 0 ] + ", " + coords1 [ 1 ] + "] - [" + coords2 [ 0 ] + ", " + coords2 [ 1 ] + "]" ); } } Herramienta Pluma . prototipo = nueva herramienta abstracta (); pentool _ prototipo _ constructor = PlumaHerramienta ; // función de la herramienta de selección SelectionTool ( widget ) { var duplicate = this ; // referencia al objeto instanciado (porque esto puede cambiar) var mouseIsDown = false ; // el botón del mouse no está presionado actualmente var startCoords = []; // coordenadas del cursor del mouse cuando se hace clic en el botón esto _ moveTo = function ( x , y ) { if ( mouseIsDown ) { setSelection ( startCoords , [ x , y ]); } }; esto _ mouseDown = function ( x , y ) { startCoords = [ x , y ]; mouseIsDown = verdadero ; }; esto _ mouseUp = function ( x , y ) { mouseIsDown = false ; }; función establecerSelección ( coords1 , coords2 ) { alerta ( " establecerSelección: [" + coords1 [ 0 ] + ", " + coords1 [ 1 ] + "] - [" + coords2 [ 0 ] + ", " + coords2 [ 1 ] + "]" ); } }; Herramienta de selección . prototipo = nueva herramienta abstracta (); Herramienta de selección . prototipo _ constructor = herramienta de selección ; // Implementación de widgets function DrawingController () { var currentTool = new SelectionTool (); // instrumento activo esto _ moveTo = function ( x , y ) { currentTool . mover a ( x , y ); }; esto _ mouseDown = function ( x , y ) { currentTool . ratón hacia abajo ( x , y ); }; esto _ mouseUp = function ( x , y ) { currentTool . ratón arriba ( x , y ); }; esto _ selectPenTool = function () { // selecciona la herramienta de selección de área currentTool = new PenTool (); }; esto _ selectSelectionTool = function () { // selecciona la herramienta lápiz currentTool = new SelectionTool (); }; } var widget = nuevo controlador de dibujo (); artilugio _ ratón hacia abajo ( 1 , 1 ); artilugio _ mover a ( 1 , 2 ); // establecerSelección: [1, 1] - [1, 2] widget . mover a ( 1 , 3 ); // establecerSelección: [1, 1] - [1, 3] widget . ratón arriba ( 1 , 3 ); artilugio _ mover a ( 1 , 4 ); artilugio _ seleccionarPlumaHerramienta (); artilugio _ ratón hacia abajo ( 1 , 1 ); artilugio _ mover a ( 1 , 2 ); // dibujarLínea: [1, 1] - [1, 2] widget . mover a ( 1 , 3 ); // dibujarLínea: [1, 2] - [1, 3] widget . ratón arriba ( 1 , 3 ); artilugio _ mover a ( 1 , 4 );

Ejemplo de CoffeeScript

Texto fuente en lenguaje CoffeeScript # Clase abstracta herramienta de clase mouseUp : -> mouseDown : -> mouseMove : -> # Clase de estados concretos PenTool extiende Tool mouseDown : (e) -> @start = x : e . coors _ x y : e . coors _ y mouseUp: (e) -> nuevas formas . Línea ( @start . x , @start . y , e . coors . x , e . coors . y ) clase ZoomTool extiende la herramienta maxZoom = 5 minZoom = 0.5 delta = 0.5 constructor : -> @zoom = 1 mouseDown : (e) -> si e . shiftKey @zoom -= delta a menos que @zoom - minZoom < delta else @zoom += delta a menos que maxZoom - @zoom < delta # Clase de widget DrawingController # private getCoords = (elemento, evento) -> caja = elemento . getBoundingClientRect () x: Matemáticas . ronda ( evento . clienteX - box . izquierda ) y: Math . round ( evento . clientY - box . top ) # constructor público: (@canvas) -> @penTool = nuevo PenTool @zoomTool = nuevo ZoomTool @currentTool = @penTool # herramienta predeterminada # Controlador de fábrica del controlador de eventos del mouse = (tipo) => (e) => e.coors = getCoords ( @canvas , e ) @currentTool [ 'mouse' + type ]( e ) e . prevenirPredeterminado () # Cuelgue los manipuladores de lona . addEventListener ( 'mouseup' , handler ( 'Up' ), off ) canvas . addEventListener ( 'mousedown' , handler ( 'Down' ), off ) canvas . addEventListener ( 'MoveMouse' , controlador ( 'Move' ), desactivado ) seleccionePenTool: -> @currentTool = @penTool seleccioneZoomTool: -> @currentTool = @zoomTool

Ejemplo de VB.NET

Aplicar una plantilla

Texto fuente en lenguaje VB.NET Espacio de nombres Digital_Patterns.Behavioral.State Interfaz pública IAutomatState Función GotApplication () As [ String ] Función CheckApplication () As [ String ] Función RentApartment () As [ String ] Función DispenseKeys () As [ String ] End Interface Interfaz pública IAutomat Sub GotApplication () Sub CheckApplication () Sub RentApartment () Sub SetState ( ByVal s As IAutomatState ) Función GetWaitingState () As IAutomatState Función GetGotApplicationState () As IAutomatState Función GetApartmentRentedState () As IAutomatState Función GetFullyRentedState () As IAutomatState Recuento de propiedades () como interfaz final Int32 Public Class Automat implementa IAutomat Private _waitingState como IAutomatState Private _gotApplicationState como IAutomatState Private _apartmentRentedState como IAutomatState Private _fullyRentedState como IAutomatState Private _state como IAutomatState Private _count como Int32 Public Sub New ( ByVal n As Int32 ) _count = n _waitingState = New WaitingState ( Me ) _gotApplicationState = New GotApplicationState ( Me ) _apartmentRentedState = New ApartmentRentedState ( Me ) _fullyRentedState = New FullyRentedState ( Me ) _state = _waitingState End Sub Public Sub GotApplication () Implementa IAutomat . TengoConsoladeAplicaciones ._ _ WriteLine ( _state.GotApplication ( ) ) End Sub Public Sub CheckApplication () Implementa IAutomat . Consola de CheckApplication . WriteLine ( _state . CheckApplication ()) End Sub Public Sub RentApartment () Implementa IAutomat . Consola RentApartment . WriteLine ( _state . RentApartment ()) Console . WriteLine ( _state . DispenseKeys ()) End Sub Public Sub SetState ( ByVal s As IAutomatState ) Implementa IAutomat . SetState _estado = s End Sub Función pública GetWaitingState () como IAutomatState implementa IAutomat . GetWaitingState Devolver _waitingState Función final Función pública GetGotApplicationState () como IAutomatState implementa IAutomat . GetGotApplicationState Retorno _gotApplicationState Función final Función pública GetApartmentRentedState () como IAutomatState implementa IAutomat . GetApartmentRentedState Devolver _apartmentRentedState Función final Función pública GetFullyRentedState () como IAutomatState implementa IAutomat . GetFullyRentedState Devolver _fullyRentedState Función final Public Property Count () As Integer implementa IAutomat . Count Get Return _count End Get Set ( ByVal value As Integer ) _count = value End Set End Property End Class La clase pública WaitingState implementa IAutomatState Private _automat como autómata Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub La función pública GotApplication () As [ String ] implementa IAutomatState . GotApplication_automat ._ _ SetState ( _automat . GetGotApplicationState ()) Devuelve "Gracias por la aplicación". función final Función pública CheckApplication () As [ String ] Implementa IAutomatState . CheckApplication Return "Tienes que enviar una solicitud". función final La función pública RentApartment () As [ String ] implementa IAutomatState . RentApartment Return "Tienes que presentar una solicitud". función final Función pública DispenseKeys () As [ String ] Implementa IAutomatState . DispenseKeys Return "Tienes que enviar una solicitud". Función final Clase final Clase pública GotApplicationState implementa IAutomatState Private _automat As Automat Private ReadOnly _random As Random Public Sub New ( ByVal automat As Automat ) _automat = automat _random = New Random ( System . DateTime . Now . Millisecond ) End Sub La función pública GotApplication () As [ String ] implementa IAutomatState . GotApplication Return "Ya recibimos su solicitud". función final Función pública CheckApplication () As [ String ] Implementa IAutomatState . CheckApplication Dim yesNo = _random . [ Siguiente ] () Modo 10 Si sí No > 4 Y También _automat . Count > 0 Luego _automat . SetState ( _automat . GetApartmentRentedState ()) Retorna "Felicitaciones, fuiste aprobado". De lo contrario _automático . SetState ( _automat . GetWaitingState ()) Devolver "Lo sentimos, no fue aprobado". Terminar si termina la función La función pública RentApartment () As [ String ] implementa IAutomatState . RentApartment Return "Debes tener tu solicitud revisada". función final Función pública DispenseKeys () As [ String ] Implementa IAutomatState . DispenseKeys Volver "Debe tener su aplicación revisada". Función final Clase final ApartmentRentedState de clase pública implementa IAutomatState Private _automat como Automat Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub La función pública GotApplication () As [ String ] implementa IAutomatState . GotApplication Return "Espera, te estamos alquilando un apartamento". función final Función pública CheckApplication () As [ String ] Implementa IAutomatState . CheckApplication Return "Espera, te estamos alquilando un apartamento". función final La función pública RentApartment () As [ String ] implementa IAutomatState . RentApartment _automat . Contar = _automat . Recuento - 1 Devolver "Alquilarle un apartamento..." Fin Función Función pública DispenseKeys () As [ String ] Implementa IAutomatState . DispenseKeys Si _automat . Cuenta <= 0 Entonces _automat . SetState ( _automat . GetFullyRentedState ()) Else _automat . SetState ( _automat . GetWaitingState ()) End If Return "¡Aquí están sus llaves!" Función final Clase final Public Class FullyRentedState implementa IAutomatState Private _automat como Automat Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub La función pública GotApplication () As [ String ] implementa IAutomatState . GotApplication Return "Lo sentimos, estamos totalmente alquilados". función final Función pública CheckApplication () As [ String ] Implementa IAutomatState . CheckApplication Return "Lo sentimos, estamos totalmente alquilados". función final La función pública RentApartment () As [ String ] implementa IAutomatState . RentApartment Volver "Lo sentimos, estamos completamente alquilados". función final Función pública DispenseKeys () As [ String ] Implementa IAutomatState . DispenseKeys Volver "Lo sentimos, estamos totalmente alquilados". Función final Clase final Clase Programa Shared Sub Main () Dim automat = New Automat ( 9 ) autómata _ GotApplication () autómata . CheckApplication () autómata . AlquilerApartamento () consola _ Leer () End Sub End Class End Espacio de nombres

El mismo ejemplo, sin aplicar la plantilla.

Texto fuente en lenguaje VB.NET Espacio de nombres Digital_Patterns.Behavioral.State Public Enum State FULLY_RENTED = 0 WAITING = 1 GOT_APPLICATION = 2 APARTMENT_RENTED = 3 End Enum Public Class RentalMethods Private ReadOnly _random As Random Private _numberApartments As Int32 Private _state As State = State . ESPERANDO Public Sub New ( ByVal n As Int32 ) _numberApartments = n _random = New Random ( System . DateTime . Now . Millisecond ) End Sub Public Sub GetApplication () Seleccione Case _state Case State . Consola FULLY_RENTED . WriteLine ( "Lo sentimos, estamos totalmente alquilados". ) Salir Seleccionar estado del caso . ESPERA_estado = Estado ._ _ Consola GOT_APPLICATION . WriteLine ( "Gracias por la solicitud" ) Salir Seleccionar estado del caso . Consola GOT_APPLICATION . WriteLine ( "Ya recibimos su solicitud" ) Salir Seleccionar estado del caso . APARTMENT_RENTED Consola . WriteLine ( "Espera, te estamos alquilando un apartamento". ) Salir Seleccionar Finalizar Seleccionar Finalizar sub Public Sub CheckApplication () Dim yesNo = _random . [ Siguiente ] () Modo 10 Seleccione Caso_estado Caso Estado . _ Consola FULLY_RENTED . WriteLine ( "Lo sentimos, estamos totalmente alquilados". ) Salir Seleccionar estado del caso . ESPERA Consola . WriteLine ( "Tiene que enviar una solicitud". ) Salir Seleccionar estado del caso . GOT_APPLICATION If yesNo > 4 AndTambién _numberApartments > 0 Entonces Consola . WriteLine ( "Felicitaciones, fue aprobado" ) _state = State . APARTMENT_RENTED RentApartment () Else Console . WriteLine ( "Lo siento, no fue aprobado" ) _state = State . EN ESPERA Terminar si sale Seleccionar estado del caso . APARTMENT_RENTED Consola . WriteLine ( "Espera, te estamos alquilando un apartamento". ) Salir Seleccionar Finalizar Seleccionar Finalizar Sub Public Sub RentApartment () Seleccione Case _state Case State . Consola FULLY_RENTED . WriteLine ( "Lo sentimos, estamos totalmente alquilados". ) Salir Seleccionar estado del caso . ESPERA Consola . WriteLine ( "Tiene que enviar una solicitud". ) Salir Seleccionar estado del caso . Consola GOT_APPLICATION . WriteLine ( "Debe tener su solicitud revisada". ) Salir Seleccionar estado del caso . APARTMENT_RENTED Consola . WriteLine ( "Alquiler un apartamento..." ) _numberApartments -= 1 DispenseKeys () Salir Seleccionar Finalizar Seleccionar final sub Public Sub DispenseKeys () Seleccione Case _state Case State . Consola FULLY_RENTED . WriteLine ( "Lo sentimos, estamos totalmente alquilados". ) Salir Seleccionar estado del caso . ESPERA Consola . WriteLine ( "Tiene que enviar una solicitud". ) Salir Seleccionar estado del caso . Consola GOT_APPLICATION . WriteLine ( "Debe tener su solicitud revisada". ) Salir Seleccionar estado del caso . APARTMENT_RENTED Consola . WriteLine ( "¡Aquí están tus llaves!" ) _state = State . ESPERANDO Salir Seleccionar Finalizar Seleccionar End Sub End Class programa de clase Shared Sub Main () Dim rentalMethods = New RentalMethods ( 9 ) métodos de alquiler . GetApplication () métodos de alquiler . CheckApplication () métodos de alquiler . RentApartment () métodos de alquiler . DispenseKeys () consola _ Leer () Fin sub Fin de espacio de nombres de fin de clase


Ejemplo de PHP5

Texto fuente en lenguaje php5 <?php /** * El patrón State controla cómo cambia el comportamiento de un objeto cuando cambia su estado interno. * Exteriormente, parece que el objeto cambia de clase. */ espacio de nombres state1 { class Client { public function __construct () { $context = new Context (); $contexto -> solicitud (); $contexto -> solicitud (); $contexto -> solicitud (); $contexto -> solicitud (); $contexto -> solicitud (); $contexto -> solicitud (); } } class Test { public static function go () { $cliente = nuevo Cliente (); } } /** * Clase con múltiples estados internos */ class Context { /** * @var ASTate */ public $state ; const ESTADO_A = 1 ; const ESTADO_B = 2 ; const ESTADO_C = 3 ; public function __construct () { $this -> setState ( Contexto :: STATE_A ); } /** * Las acciones de contexto se delegan a los objetos de estado para su procesamiento */ solicitud de función pública () { $this -> state -> handle (); } /** * Esta es una forma de implementar el cambio de estado * @param $estado es el estado seleccionado, las posibles opciones se enumeran en la lista de constantes Contexto::ESTADO_.. */ public function setState ( $estado ) { if ( $ state == Contexto :: STATE_A ) { $this -> state = new ConcreteStateA ( $this ); } elseif ( $estado == Contexto :: ESTADO_B ) { $este -> estado = new EstadoConcretoB ( $este ); } elseif ( $estado == Contexto :: ESTADO_C ) { $este -> estado = new EstadoConcretoC ( $este ); } } } /** * Interfaz común para todos los estados concretos. * Todos los estados implementan la misma interfaz y, por lo tanto, son intercambiables. */ class AState { /** * @var Context almacena una referencia al contexto para un cambio de estado conveniente */ protected $context ; public function __construct ( $contexto ) { $this -> context = $contexto ; } /** * El procesamiento en diferentes estados puede diferir. * Si ASTate no es solo una interfaz, sino una clase abstracta, * entonces puede contener procesamiento estándar, entonces las clases de estados concretos describirán solo sus características con respecto al comportamiento estándar. */ identificador de función pública () { echo " \n identificador estándar" ; } } /** * Luego viene un conjunto de estados específicos que procesan las solicitudes del Contexto. * Cada clase proporciona su propia implementación de solicitud. * Por lo tanto, cuando el objeto Contexto pasa a otro estado, su comportamiento también cambia. */ class ConcreteStateA extiende AState { public function handle () { echo " \n State A handle" ; // alternar estado $this -> context -> setState ( Contexto :: STATE_B ); } } class ConcreteStateB extiende AState { public function handle () { echo " \n State B handle" ; // alternar estado $this -> context -> setState ( Contexto :: STATE_C ); } } class ConcreteStateC extiende AState { public function handle () { echo " \n State C handle" ; // alternar estado $this -> context -> setState ( Contexto :: STATE_A ); } } prueba :: ir (); } Un ejemplo con un autómata de patrones head first en php5 <?php /** * Un ejemplo más específico basado en el patrón "Estado". * El patrón State controla cómo cambia el comportamiento de un objeto cuando cambia su estado interno. * Exteriormente, parece que el objeto cambia de clase. */ espacio de nombres state2 { class Client { public function __construct () { $context = new Context (); $contexto -> dispensar (); $contexto -> insertarCuarto (); $contexto -> TurnCrank (); $contexto -> insertarCuarto (); $contexto -> TurnCrank (); $contexto -> insertarCuarto (); $contexto -> TurnCrank (); } } class Test { public static function go () { $cliente = nuevo Cliente (); } } /** * Clase con múltiples estados internos */ class Context { /** * @var ASTate */ public $state ; /** * Estados posibles */ const STATE_SOLD_OUT = 1 ; const ESTADO_NO_CUARTO_ESTADO = 2 ; const ESTADO_HAS_CUARTO_ESTADO = 3 ; const ESTADO_VENDIDO_ESTADO = 4 ; const ESTADO_GANADOR_ESTADO = 5 ; /** * @var int ¿Cuánto chicle hay en la máquina? */ público $contar = 2 ; public function __construct () { $this -> setState ( Contexto :: STATE_NO_QUARTER_STATE ); } /** * Las acciones de contexto se delegan a los objetos de estado para su procesamiento */ public function insertQuarter () { $this -> state -> insertQuarter (); } public function ejectQuarter () { $this -> state -> ejectQuarter (); } public function turnCrank () { $this -> state -> turnCrank (); $este -> estado -> dispensar (); } public function dispensar () { $this -> estado -> dispensar (); } /** * Esta es una forma de implementar el cambio de estado * @param $estado es el estado seleccionado, las posibles opciones se enumeran en la lista de constantes Contexto::ESTADO_.. */ public function setState ( $estado ) { if ( $ state == Contexto :: STATE_SOLD_OUT ) { $this -> state = new ConcreteStateSoldOut ( $this ); } elseif ( $estado == Contexto :: ESTADO_SIN_CUARTO_ESTADO ) { $este -> estado = new EstadoConcretoSinCuarto ( $este ); } elseif ( $estado == Contexto :: ESTADO_HAS_CUARTO_ESTADO ) { $este -> estado = nuevo EstadoConcretoHasCuarto ( $este ); } elseif ( $estado == Contexto :: ESTADO_VENDIDO_ESTADO ) { $este -> estado = new EstadoConcretoVendidoEstado ( $este ); } elseif ( $estado == Contexto :: ESTADO_GANADOR_ESTADO ) { $este -> estado = nuevo EstadoConcretoGanadorEstado ( $este ); } } public function liberarBola () { if ( $this -> count > 0 ) { echo "Bola lanzada" ; $esto -> contar -= 1 ; } else { echo "No hay bolas para soltar :(" ; } } } /** * Interfaz común para todos los estados concretos. * Todos los estados implementan la misma interfaz y, por lo tanto, son intercambiables. */ class AState { /** * @var Context almacena una referencia al contexto para un cambio de estado conveniente */ protected $context ; public function __construct ( & $contexto ) { $this -> context =& $context ; } /** * El procesamiento en diferentes estados puede diferir. * Si ASTate no es solo una interfaz, sino una clase abstracta, * entonces puede contener procesamiento estándar, entonces las clases de estados concretos describirán solo sus características con respecto al comportamiento estándar. */ public function insertQuarter () { echo " \n lol, no puedes hacer eso" ; } public function ejectQuarter () { echo " \n lol, no puedes hacer eso" ; } public function turnCrank () { echo " \n lol, no puedes hacer eso" ; } public function dispensar () { echo " \n lol, no puedes hacer eso" ; } } /** * Luego viene un conjunto de estados específicos que procesan las solicitudes del Contexto. * Cada clase proporciona su propia implementación de solicitud. * Por lo tanto, cuando el objeto Contexto pasa a otro estado, su comportamiento también cambia. */ clase ConcreteStateSoldOut extiende AState { public function insertQuarter () { echo " \n lo siento, estoy agotado, no puedo tomar trimestres" ; } } class EstadoConcretoSinCuarto extiende AEstado { public function insertarCuarto () { echo " \n obtuve un cuarto, ¡sí!" ; // alternar estado $esto -> contexto -> setState ( Contexto :: STATE_HAS_QUARTER_STATE ); } } class ConcreteStateHasQuarter extiende AState { public function ejectQuarter () { echo " \n recupera tu dinero" ; // alternar estado $esto -> contexto -> establecerEstado ( Contexto :: ESTADO_NO_CUARTO_ESTADO ); } public function turnCrank () { echo " \n te volviste" ; $ganador = rand ( 1 , 10 ) == 10 ? 1 : 0 ; if ( $ganador ) { $esto -> contexto -> establecerEstado ( Contexto :: ESTADO_GANADOR_ESTADO ); } else { $this -> context -> setState ( Contexto :: STATE_SOLD_STATE ); } } } class ConcreteStateSoldState extends AState { public function dispensar () { echo " \n dispensando, ¡sí!" ; $this -> context -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Contexto :: STATE_SOLD_OUT ); } else { // alternar estado $this -> context -> setState ( Contexto :: STATE_NO_QUARTER_STATE ); } } } class ConcreteStateWinnerState extiende AState { public function dispensar () { echo " \n dispensando, ¡sí!" ; $this -> context -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Contexto :: STATE_SOLD_OUT ); } else { echo " \n pd eres el GANADOR, ¡obtienes una bola extra!" ; $this -> context -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Contexto :: STATE_SOLD_OUT ); } else { $this -> context -> setState ( Contexto :: STATE_NO_QUARTER_STATE ); } } } } prueba :: ir (); }