Stav (návrhový vzor)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 25. března 2014; kontroly vyžadují 20 úprav .
Stát
Stát
Typ behaviorální
Popsáno v Návrhové vzory Ano

State ( angl.  State ) je behaviorální návrhový vzor . Používá se v těch případech, kdy během provádění programu musí objekt změnit své chování v závislosti na svém stavu.

Vzor se skládá ze 3 bloků:

Widget je třída, jejíž objekty by měly měnit své chování v závislosti na stavu.

ISate je rozhraní , které musí implementovat každý z konkrétních stavů. Prostřednictvím tohoto rozhraní objekt Widget interaguje se stavem delegováním volání metod na něj. Rozhraní by mělo obsahovat prostředky pro zpětnou vazbu k objektu, jehož chování má být změněno. K tomu slouží událost ( vzor Publisher - Subscriber ). To je nezbytné pro nahrazení objektu stavu během provádění programu, když nastanou události. Mohou nastat situace, kdy samotný widget pravidelně dotazuje objekt stavu na přechod.

StateA ... StateZ - třídy konkrétních stavů. Měl by obsahovat informaci o tom, za jakých podmínek a v jakých stavech může objekt přejít ze současného stavu. Objekt může například přejít ze StavuA do StavuB a StavC a ze StavuB zpět do StavuA a tak dále. Objekt jednoho z nich musí obsahovat widget, když je vytvořen.

Použití tohoto vzoru může být obtížné, pokud státy potřebují komunikovat nebo pokud jeden stav nastavuje vlastnosti druhého. V tomto případě budete potřebovat globální objekt, což není příliš dobré architektonické řešení.

Příklady

Příklad C++

Zdrojový text v C++ #pragma jednou #include <řetězec> #include <iostream> třída Stát ; třída StateContext ; třída SolidState ; třída LiquidState ; třída GasState ; třída Stát { std :: stringname ; _ veřejnost : State ( const std :: string & name ) : jméno ( jméno ) {} std :: string GetName () { návratové jméno ; } virtual void Freeze ( StateContext * ) = 0 ; virtuální void Teplo ( StateContext * ) = 0 ; }; třídy StateContext { soukromý : Stát * stát ; veřejnost : StateContext ( State * state ) : state ( state ) {} void freeze () { std :: cout << "Zamrznutí " << stav -> GetName () << "..." << std :: endl ; stav -> Zmrazit ( toto ); } voidHeat ( ) { std :: cout << "Topení " << stav -> GetName () << "..." << std :: endl ; stav -> Teplo ( toto ); } void SetState ( State * s ) { std :: cout << "Změna stavu z " << stav -> GetName () << " na " << s -> GetName () << "..." << std :: endl ; smazat stav ; stav = s ; } State * GetState () { návratový stav ; } ~ StateContext () { smazat stav ; } }; třída SolidState : veřejný stav { veřejnost : SolidState () : State ( "Solid" ) {} virtual void Freeze ( StateContext * state ); virtuální void Teplo ( StateContext * state ); }; třída LiquidState : veřejný stát { veřejnost : LiquidState () : State ( "Liquid" ) {} virtual void Freeze ( StateContext * state ); virtuální void Teplo ( StateContext * state ); }; třída GasState : veřejný stát { veřejnost : GasState () : State ( "Gas" ) {} virtual void Freeze ( StateContext * state ); virtuální void Teplo ( StateContext * state ); }; void SolidState::Freeze ( StateContext * state ) { std :: cout << "Nic se neděje" << std :: endl ; } void SolidState::Heat ( StateContext * state ) { state -> SetState ( new LiquidState ()); } void LiquidState::Freeze ( StateContext * state ) { state -> SetState ( new SolidState ()); } void LiquidState::Heat ( StateContext * state ) { state -> SetState ( new GasState ()); } void GasState::Freeze ( StateContext * state ) { state -> SetState ( new LiquidState ()); } void GasState::Heat ( StateContext * state ) { std :: cout << "Nic se neděje" << std :: endl ; } neplatný test () { StateContext * sc = new StateContext ( new SolidState ()); sc -> Teplo (); sc -> Teplo (); sc -> Teplo (); sc -> zmrazení (); sc -> zmrazení (); sc -> zmrazení (); smazat sc ; }

Příklad v C#

Použití šablony

Zdrojový text v C# pomocí System ; jmenný prostor Digital_Patterns.Behavioral.State { public interface IAutomatState { String GotApplication (); StringCheckApplication ( ); String RentApartment (); StringDispenseKeys ( ); } veřejné rozhraní IAutomat { void GotApplication (); void CheckApplication (); neplatné PronájemApartment (); void SetState ( IAutomatState s ); IAutomatState GetWaitingState (); IAutomatState GetGotApplicationState (); IAutomatState GetApartmentRentedState (); IAutomatState GetFullyRentedState (); Int32 Count { get ; nastavit ; } } public class Automat : IAutomat { private IAutomatState _waitingState ; private IAutomatState _gotApplicationState ; private IAutomatState _apartmentRentedState ; private IAutomatState _fullyRentedState ; private IAutomatState _state ; private Int32_count ; _ public Automat ( Int32 n ) { _count = n ; _waitingState = new WaitingState ( this ); _gotApplicationState = new GotApplicationState ( this ); _apartmentRentedState = new ApartmentRentedState ( this ); _fullyRentedState = new FullyRentedState ( this ); _state = _waitingState ; } public void GotApplication () { Console . WriteLine ( _state.GotApplication ( ) ); } public void CheckApplication () { Console . WriteLine ( _state.CheckApplication ( ) ); } public void RentApartment () { Console . WriteLine ( _state.RentApartment ( ) ); Konzole . WriteLine ( _state . DispenseKeys ()); } public void SetState ( IAutomatState 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 { get { return _count ; } set { _počet = hodnota ; } } } public class WaitingState : IAutomatState { private Automat _automat ; public WaitingState ( Automat automat ) { _automat = automat ; } public String GotApplication () { _automat . SetState ( _automat . GetGotApplicationState ()); návrat "Děkujeme za přihlášku." ; } public String CheckApplication () { return "Musíte odeslat žádost." ; } public String RentApartment () { return "Musíte podat žádost." ; } public String DispenseKeys () { return "Musíte odeslat žádost." ; } } public class GotApplicationState : IAutomatState { private Automat _automat ; soukromé pouze pro čtení Náhodný _náhodný ; public GotApplicationState ( Automat automat ) { _automat = automat ; _random = new Random ( System . DateTime . Now . Milisecond ); } public String GotApplication () { return "Vaši aplikaci již máme." ; } public String CheckApplication () { var yesNo = _random . Další () % 10 ; if ( anoNe > 4 && _automat . Počet > 0 ) { _automat . SetState ( _automat . GetApartmentRentedState ()); return "Gratulujeme, byli jste schváleni." ; } else { _automatic . SetState ( _automat . GetWaitingState ()); return "Promiň, nebyl jsi schválen." ; } } public String RentApartment () { return "Musíte nechat zkontrolovat aplikaci." ; } public String DispenseKeys () { return "Musíte nechat zkontrolovat aplikaci." ; } } public class ApartmentRentedState : IAutomatState { private Automat _automat ; public ApartmentRentedState ( Automat automat ) { _automat = automat ; } public String GotApplication () { return "Počkej, pronajmeme ti byt." ; } public String CheckApplication () { return "Počkej, pronajímáme ti byt." ; } public String RentApartment () { _automat . Počet = _automat . Počet - 1 ; návrat "Pronajímám vám byt..." ; } public String DispenseKeys () { if ( _automat . Počet <= 0 ) _automat . SetState ( _automat . GetFullyRentedState ()); jinak _automaticky . SetState ( _automat . GetWaitingState ()); návrat "Tady máš klíče!" ; } } public class FullyRentedState : IAutomatState { private Automat _automat ; public FullyRentedState ( Automat automat ) { _automat = automat ; } public String GotApplication () { return "Je nám líto, jsme plně pronajati." ; } public String CheckApplication () { return "Omlouváme se, jsme plně pronajati." ; } public String RentApartment () { return "Je nám líto, jsme plně pronajati." ; } public String DispenseKeys () { return "Omlouváme se, jsme plně pronajati." ; } } class Program { static void Main ( string [] args ) { var automat = new Automat ( 9 ); automat . GotApplication (); automat . CheckApplication (); automat . PronájemByt (); } } }

Stejný příklad, bez použití šablony

Zdrojový text v C# pomocí System ; jmenný prostor 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 ; private Int32 _čísloApartmány ; private State _state = State . ČEKÁNÍ ; public RentalMethods ( Int32 n ) { _numberApartments = n ; _random = new Random ( System . DateTime . Now . Milisecond ); } public void GetApplication () { switch ( _state ) { case State . FULLY_RENTED : Konzole . WriteLine ( "Omlouváme se, jsme plně pronajati." ); zlomit ; stát případu . WAITING : _state = State . GOT_APPLICATION ; Konzole . WriteLine ( "Děkujeme za aplikaci." ); zlomit ; stát případu . GOT_APPLICATION : Konzole . WriteLine ( "Vaši žádost už máme." ); zlomit ; stát případu . APARTMENT_RENTED : Konzole . WriteLine ( "Vydrž, pronajímáme ti byt." ); zlomit ; } } public void CheckApplication () { var yesNo = _random . další ()% 10 ; switch ( _state ) { case State . FULLY_RENTED : Konzole . WriteLine ( "Omlouváme se, jsme plně pronajati." ); zlomit ; stát případu . ČEKÁNÍ : Konzole . WriteLine ( "Musíte odeslat žádost." ); zlomit ; stát případu . GOT_APPLICATION : if ( yesNe > 4 && _numberApartments > 0 ) { Console . WriteLine ( "Blahopřejeme, byli jste schváleni." ); _state = Stát . BYT_PRONAJAT ; PronájemByt (); } else { Konzole . WriteLine ( "Je nám líto, nebyli jste schváleni." ); _state = Stát . ČEKÁNÍ ; } přestávka ; stát případu . APARTMENT_RENTED : Konzole . WriteLine ( "Vydrž, pronajímáme ti byt." ); zlomit ; } } public void RentApartment () { switch ( _state ) { case State . FULLY_RENTED : Konzole . WriteLine ( "Omlouváme se, jsme plně pronajati." ); zlomit ; stát případu . ČEKÁNÍ : Konzole . WriteLine ( "Musíte odeslat žádost." ); zlomit ; stát případu . GOT_APPLICATION : Konzole . WriteLine ( "Musíte nechat zkontrolovat aplikaci." ); zlomit ; stát případu . APARTMENT_RENTED : Konzole . WriteLine ( "Pronájem bytu..." ); _čísloApartmány --; DispenseKeys (); zlomit ; } } public void DispenseKeys () { switch ( _state ) { case State . FULLY_RENTED : Konzole . WriteLine ( "Omlouváme se, jsme plně pronajati." ); zlomit ; stát případu . ČEKÁNÍ : Konzole . WriteLine ( "Musíte odeslat žádost." ); zlomit ; stát případu . GOT_APPLICATION : Konzole . WriteLine ( "Musíte nechat zkontrolovat aplikaci." ); zlomit ; stát případu . APARTMENT_RENTED : Konzole . WriteLine ( "Tady jsou vaše klíče!" ); _state = Stát . ČEKÁNÍ ; zlomit ; } } } class Program { static void Main ( string [] args ) { var rentalMethods = new RentalMethods ( 9 ); metody pronájmu . GetApplication (); metody pronájmu . CheckApplication (); metody pronájmu . PronájemByt (); metody pronájmu . DispenseKeys (); } } }

Příklad Java

Zdroj Java public class StateExample { public static void main ( String [] args ) { StateContext context = new StateContext (); kontextu . teplo (); kontextu . teplo (); kontextu . teplo (); kontextu . zmrazit (); kontextu . zmrazit (); kontextu . zmrazit (); // VÝSTUP: // Zahřívání pevné látky... // Změna skupenství na kapalinu... // Zahřívání kapalné látky... // Změna skupenství na plynné... // Zahřívání plynné látky... // Nic se neděje . // Zmrazování plynné látky... // Změna skupenství na kapalinu... // Zamrzání kapalné látky... // Změna skupenství na pevnou látku... // Zamrzání pevné látky... // Nic se neděje. } } interface State { String getName (); void freeze ( StateContext context ); void heat ( StateContext context ); } class SolidState implementuje State { private static final String NAME = "solid" ; public String getName () { return JMÉNO ; } public void freeze ( StateContext context ) { System . ven . println ( "Nic se neděje." ); } public void heat ( StateContext context ) { context . setState ( new LiquidState ()); } } class LiquidState implementuje State { private static final String NAME = "liquid" ; public String getName () { return JMÉNO ; } public void freeze ( StateContext context ) { context . setState ( newSolidState ( )); } public void heat ( StateContext context ) { context . setState ( new GaseousState ()); } } class GaseousState implementuje stav { private static final String NAME = "plynný" ; public String getName () { return JMÉNO ; } public void freeze ( StateContext context ) { context . setState ( new LiquidState ()); } public void heat ( StateContext context ) { System . ven . println ( "Nic se neděje." ); } } class StateContext { private State state = new SolidState (); public void freeze () { System . ven . println ( "Zmrazení " + stav . getName () + " substance..." ); stát . zmrazit ( toto ); } public void heat () { System . ven . println ( "Zahřívání " + stav . getName () + " substance..." ); stát . teplo ( toto ); } public void setState ( State state ) { System . ven . println ( "Změna stavu na " + stav . getName () + "..." ); toto . stát = stát ; } public State getState () { return state ; } }

Příklad Pythonu

Zdrojový kód v Pythonu z abc import ABCMeta , abstraktní metoda stav třídy ( metatřída = ABCMeta ): @abstractmethod def eat ( self ) -> str : pass @abstractmethod def find_food ( self ) -> str : pass @abstractmethod def move ( self ) -> str : pass @abstractmethod def dream ( self ) -> str : pass třída SleepState ( State ): def eat ( self ) -> str : return 'nemohu jíst, když spím' def find_food ( self ) -> str : return 'najde jídlo, ale pouze ve svých snech' def move ( self ) -> str : return 'nemohu se pohybovat, když spím' def dream ( self ) -> str : návrat 'spi a měj nádherný sen' třída OnGroundState ( State ): def eat ( self ) -> str : return 'vysype sklizené škeble na břicho a začne je pomalu jíst' def find_food ( self ) -> str : return 'najde páchnoucí, ale poživatelnou mršinu uvízlé velryby' def move ( self ) -> str : return 'nemotorně se plazí podél pobřeží' def dream ( self ) -> str : return 'zastaví se na chvíli, sní o známé ženě' třída InWaterState ( State ): def eat ( self ) -> str : return 'nemohu jíst ve vodě' def find_food ( self ) -> str : return 'orá mořské dno kly, chytá škeble svými vibrissae' def move ( self ) -> str : return 'ladně se prodírá vlnami světových oceánů' def dream ( self ) -> str : return 'nespěte ani nesni ve vodě - to je příliš těžké' třída Mrož : def __init__ ( self , state : State ) -> None : self . _state = stát def change_state ( self , state : State ) -> None : self . _state = stát def eat ( self ) -> None : self . _execute ( 'jíst' ) def find_food ( self ) -> None : self . _execute ( 'najít_jídlo' ) def move ( self ) -> None : self . _execute ( 'přesunout' ) def dream ( self ) -> None : self . _execute ( 'sen' ) def _execute ( self , operation : str ) -> None : try : func = getattr ( self . _state , operation ) print ( 'Mrož {} .' . format ( func ())) kromě AttributeError : print ( 'Mrož dělá toto nemůžu.' ) if __name__ == '__main__' : sleep = SleepState () on_ground = OnGroundState () in_water = InWaterState () mrož = Mrož ( on_ground ) print ( 'OUTPUT:' ) mrož . change_state ( in_water ) mrož . pohybovat () mrož . find_food () mrož . change_state ( on_ground ) mrož . jíst () mrož . pohybovat () mrož . sen () mrož . change_state ( spánek ) mrož . sen () ''' VÝSTUP: Mrož se ladně prodírá vlnami oceánů. Mrož orá svými kly mořské dno a svými vibrissami chytá měkkýše. Mrož vysype vytěžené měkkýše na břicho a začne je pomalu požírat. Mrož se nemotorně plazí podél pobřeží. Mrož se na chvíli zastaví a sní o jedné známé samici. Mrož spí a vidí nádherný sen. '''

Příklad Javascriptu

Příklad se změnou stavu ze státu.

Zdrojový text v javascriptu // Stav "rozhraní". function State () { this . someMetoda = function () { }; toto . nextState = function () { }; } // státní implementace // funkce prvního stavu StateA ( widjet ) { var duplicate = this ; // odkaz na vytvořený objekt (protože se to může změnit) toto . someMethod = function () { alert ( "StateA.someMethod" ); duplikát . nextState (); }; toto . nextState = function () { alert ( "StavA > StavB" ); widget . onNextState ( nový stavB ( widjet ) ); }; } StavA . prototyp = nový stav (); StateA . prototyp . konstruktor = StavA ; // funkce druhého stavu StateB ( widjet ) { var duplicate = this ; toto . someMethod = function () { alert ( "StateB.someMethod" ); duplikát . nextState (); }; toto . nextState = function () { alert ( "StateB > StateA" ); widget . onNextState ( nový stavA ( widjet ) ); }; } StavB . prototyp = nový stav (); StavB . prototyp . konstruktor = StavB ; // Widget "rozhraní" function Widget () { this . someMetoda = function () { }; toto . onNextState = function ( state ) { }; } // Implementace widgetu function Widget1 () { var state = new StateA ( this ); toto . someMethod = function () { state . nějakáMetoda (); }; toto . onNextState = function ( newState ) { state = newState ; }; } Widget1 . prototyp = nový widget (); Widget1 . prototyp . konstruktor = Widget1 ; // použití var widget = new Widget1 (); widget . nějakáMetoda (); // StateA.someMethod // StateA > widget StateB . nějakáMetoda (); // StateB.someMethod // StateB > StateA

Změna stavů voláním metody na Widgetu (z anglické verze článku).

Zdrojový text v javascriptu // Stav "rozhraní". function AbstractTool () { this . moveTo = funkce ( x , y ) { }; toto . mouseDown = funkce ( x , y ) { }; toto . mouseUp = funkce ( x , y ) { }; } // státní implementace // funkce nástroje tužka PenTool ( widjet ) { var duplicate = this ; // odkaz na vytvořený objekt (protože se to může změnit) var mouseIsDown = false ; // tlačítko myši není aktuálně stisknuto var lastCoords = []; // minulé souřadnice kurzoru myši toto . moveTo = function ( x , y ) { if ( mouseIsDown && lastCoords . length ) { drawLine ( lastCoords , [ x , y ]); } lastCoords = [ x , y ]; }; toto . mouseDown = function ( x , y ) { mouseIsDown = true ; lastCoords = [ x , y ]; }; toto . mouseUp = function ( x , y ) { mouseIsDown = false ; }; function drawLine ( coords1 , coords2 ) { alert ( "drawLine: [" + coords1 [ 0 ] + ", " + coords1 [ 1 ] + "] - [" + coords2 [ 0 ] + ", " + coords2 [ 1 ] + "]" ); } } PenTool . prototyp = new AbstractTool (); pentool . prototyp . konstruktor = PenTool ; // funkce nástroje pro výběr SelectionTool ( widget ) { var duplicate = this ; // odkaz na vytvořený objekt (protože se to může změnit) var mouseIsDown = false ; // tlačítko myši není aktuálně stisknuto var startCoords = []; // souřadnice kurzoru myši při kliknutí na tlačítko toto . moveTo = function ( x , y ) { if ( mouseIsDown ) { setSelection ( startCoords , [ x , y ]); } }; toto . mouseDown = function ( x , y ) { startCoords = [ x , y ]; mouseIsDown = true ; }; toto . mouseUp = function ( x , y ) { mouseIsDown = false ; }; function setSelection ( coords1 , coords2 ) { alert ( "setSelection: [" + coords1 [ 0 ] + ", " + coords1 [ 1 ] + "] - [" + coords2 [ 0 ] + ", " + coords2 [ 1 ] + "]" ); } }; SelectionTool . prototyp = new AbstractTool (); SelectionTool . prototyp . konstruktor = SelectionTool ; // Implementace widgetu function DrawingController () { var currentTool = new SelectionTool (); // aktivní nástroj toto . moveTo = function ( x , y ) { currentTool . moveTo ( x , y ); }; toto . mouseDown = function ( x , y ) { currentTool . mouseDown ( x , y ); }; toto . mouseUp = function ( x , y ) { currentTool . mouseUp ( x , y ); }; toto . selectPenTool = function () { // výběr nástroje pro výběr oblasti currentTool = new PenTool (); }; toto . selectSelectionTool = function () { // výběr nástroje tužka currentTool = new SelectionTool (); }; } var widget = new DrawingController (); widget . mousedown ( 1 , 1 ); widget . moveTo ( 1 , 2 ); // setSelection: [1, 1] - [1, 2] widget . moveTo ( 1 , 3 ); // setSelection: [1, 1] - [1, 3] widget . mouseUp ( 1 , 3 ); widget . moveTo ( 1 , 4 ); widget . selectPenTool (); widget . mousedown ( 1 , 1 ); widget . moveTo ( 1 , 2 ); // drawLine: [1, 1] - [1, 2] widget . moveTo ( 1 , 3 ); // drawLine: [1, 2] - [1, 3] widget . mouseUp ( 1 , 3 ); widget . moveTo ( 1 , 4 );

Příklad CoffeeScript

Zdrojový text v jazyce CoffeeScript # Abstract class class Tool mouseUp : -> mouseDown : -> mouseMove : -> # Třída konkrétních stavů PenTool rozšiřuje Nástroj mouseDown : (e) -> @start = x : e . coors . x y : e . coors . y mouseUp : (e) -> nové tvary . Řádek ( @start . x , @ start . y , e . coors . x , e . coors . y ) třída ZoomTool rozšiřuje nástroj maxZoom = 5 minZoom = 0,5 delta = 0,5 konstruktor: -> @zoom = 1 mouseDown : (e) -> pokud e . shiftKey @zoom -= delta , pokud @zoom - minZoom < delta jinak @zoom += delta , pokud maxZoom - @zoom < delta # Widget class DrawingController # private getCoords = (elem, událost) -> box = elem . getBoundingClientRect () x: Matematika . kolo ( event . clientX - box . left ) y : Math . kolo ( event . clientY - box . top ) # veřejný konstruktor : (@canvas) -> @penTool = nový nástroj PenTool @zoomTool = nový nástroj ZoomTool @currentTool = @penTool # výchozí nástroj # Obsluha události myši tovární handler = (typ) => (e) => e.coors = getCoords ( @canvas , e ) @currentTool [ 'myš' + typ ]( e ) e . zabránitVýchozí () # Zavěste manipulátory s plátnem . addEventListener ( 'mouseup' , handler ( 'Up' ), off ) canvas . addEventListener ( 'mousedown' , handler ( 'Down' ), off ) canvas . addEventListener ( 'mousemove' , handler ( 'Move' ), off ) selectPenTool : -> @currentTool = @penTool selectZoomTool : -> @currentTool = @zoomTool

Příklad VB.NET

Použití šablony

Zdrojový text v jazyce VB.NET Jmenný prostor Digital_Patterns.Behavioral.State Veřejné rozhraní IAutomatState Function GotApplication () As [ String ] Function CheckApplication () As [ String ] Function RentApartment () As [ String ] Function DispenseKeys () As [ String ] End Interface Veřejné rozhraní IAutomat Sub GotApplication () Sub CheckApplication () Sub RentApartment () Sub SetState ( ByVal s As IAutomatState ) Funkce GetWaitingState () As IAutomatState Funkce GetGotApplicationState () As IAutomatState Funkce GetApartmentRentedState () As IAutomatState Funkce GetFullyRentedState () As IAutomatState Property Count () Jako Int32 End Interface Public Class Automat Implementuje IAutomat Private _waitingState As IAutomatState Private _gotApplicationState As IAutomatState Private _apartmentRentedState As IAutomatState Private _fullyRentedState As IAutomatState Private _state As IAutomatState Private _count As Int32 Public Sub New ( ByVal n As Int32 ) _count = n _waitingState = Nový WaitingState ( ) _gotApplicationState = New GotApplicationState ( ) _apartmentRentedState = Nový ApartmentRentedState ( ) _fullRentedState = SubState New ( ) _ _ _ _ _ Public Sub GotApplication () Implementuje IAutomat . GotApplicationConsole . _ WriteLine ( _state.GotApplication ( ) ) End Sub Public Sub CheckApplication () Implementuje IAutomat . CheckApplication Console . WriteLine ( _state . CheckApplication ()) End Sub Public Sub RentApartment () Implementuje IAutomat . RentApartment Console . WriteLine ( _state . RentApartment ()) Konzole . WriteLine ( _state . DispenseKeys ()) End Sub Public Sub SetState ( ByVal s As IAutomatState ) Implementuje IAutomat . SetState _state = s End Sub Veřejná funkce GetWaitingState () As IAutomatState implementuje IAutomat . GetWaitingState Return _waitingState End Function Veřejná funkce GetGotApplicationState () As IAutomatState Implementuje IAutomat . GetGotApplicationState Return _gotApplicationState End Function Veřejná funkce GetApartmentRentedState () Jako IAutomatState implementuje IAutomat . GetApartmentRentedState Return _apartmentRentedState End Function Veřejná funkce GetFullyRentedState () As IAutomatState Implementuje IAutomat . GetFullyRentedState Return _fullyRentedState End Function Public Property Count () As Integer Implementuje IAutomat . Count Get Return _count End Get Set ( ByVal value As Integer ) _count = value End Set End Vlastnost End Class Public Class WaitingState Implementuje IAutomatState Private _automat jako automat Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub Veřejná funkce GotApplication () As [ String ] Implementuje IAutomatState . GotApplication_automat . _ SetState ( _automat . GetGotApplicationState ()) Return "Díky za aplikaci." koncová funkce Public Function CheckApplication () As [ String ] Implementuje IAutomatState . CheckApplication Return "Musíte odeslat žádost." koncová funkce Public Function RentApartment () As [ String ] Implementuje IAutomatState . RentApartment Return "Musíte podat žádost." koncová funkce Public Function DispenseKeys () As [ String ] Implementuje IAutomatState . DispenseKeys Return "Musíte podat žádost." Koncová funkce Koncová třída Public Class GotApplicationState Implementuje 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 . Milisecond ) End Sub Veřejná funkce GotApplication () As [ String ] Implementuje IAutomatState . GotApplication Return "Už jsme dostali vaši žádost." koncová funkce Public Function CheckApplication () As [ String ] Implementuje IAutomatState . CheckApplication Dim yesNo = _random . [ Další ] () Mod 10 Pokud anoNe > 4 AndTaké _automat . Počet > 0 Potom _automat . SetState ( _automat . GetApartmentRentedState ()) Return "Blahopřejeme, byli jste schváleni." Jinak _automaticky . SetState ( _automat . GetWaitingState ()) Return "Je nám líto, nebyli jste schváleni." End If End Funkce Public Function RentApartment () As [ String ] Implementuje IAutomatState . RentApartment Return "Musíte nechat zkontrolovat svou žádost." koncová funkce Public Function DispenseKeys () As [ String ] Implementuje IAutomatState . DispenseKeys Return "Musíte nechat zkontrolovat aplikaci." Koncová funkce Koncová třída Veřejná třída ApartmentRentedState Implementuje IAutomatState Private _automat jako automat Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub Veřejná funkce GotApplication () As [ String ] Implementuje IAutomatState . GotApplication Return "Počkejte, pronajmeme vám apartmán." koncová funkce Public Function CheckApplication () As [ String ] Implementuje IAutomatState . CheckApplication Return "Vydržte, pronajímáme vám byt." koncová funkce Public Function RentApartment () As [ String ] Implementuje IAutomatState . RentApartment _automat . Počet = _automat . Count - 1 Return "Pronájem bytu......" End Function Public Function DispenseKeys () As [ String ] Implementuje IAutomatState . DispenseKeys If _automat . Počet <= 0 Potom _automat . SetState ( _automat . GetFullyRentedState ()) Jinak _automat . SetState ( _automat . GetWaitingState ()) End If Return "Tady jsou vaše klíče!" Koncová funkce Koncová třída Public Class FullyRentedState Implementuje IAutomatState Private _automat jako Automat Public Sub New ( ByVal automat As Automat ) _automat = automat End Sub Veřejná funkce GotApplication () As [ String ] Implementuje IAutomatState . GotApplication Return "Je nám líto, jsme plně pronajati." koncová funkce Public Function CheckApplication () As [ String ] Implementuje IAutomatState . CheckApplication Return "Je nám líto, jsme plně pronajati." koncová funkce Public Function RentApartment () As [ String ] Implementuje IAutomatState . RentApartment Return "Omlouváme se, jsme plně pronajati." koncová funkce Public Function DispenseKeys () As [ String ] Implementuje IAutomatState . DispenseKeys Return "Je nám líto, jsme plně pronajati." Koncová funkce Koncová třída Třídní program Sdílený Dílčí hlavní () Dim automat = Nový automat ( 9 ) automat . GotApplication () automat . CheckApplication () automat . Pronájem bytu () Konzole . Číst () End Sub End Class End Namespace

Stejný příklad, bez použití šablony

Zdrojový text v jazyce VB.NET Namespace Digital_Patterns.Behavioral.State Stav veřejného výčtu FULLY_RENTED = 0 WAITING = 1 GOT_APPLICATION = 2 APARTMENT_RENTED = 3 End Enum Metody pronájmu veřejné třídy Soukromé Pouze pro čtení _random Jako náhodné Soukromé _čísloApartmány Jako Int32 Soukromé _stav Jako Stav = Stav . ČEKÁNÍ Public Sub New ( ByVal n As Int32 ) _numberApartments = n _random = New Random ( System . DateTime . Now . Milisecond ) End Sub Public Sub GetApplication () Vyberte Case _state Case State . Konzole FULLY_RENTED . WriteLine ( "Omlouváme se, jsme plně pronajati." ) Ukončit Select Case State . WAITING_state = Stav . _ GOT_APPLICATION Konzole . WriteLine ( "Děkujeme za aplikaci." ) Konec Vyberte stav případu . GOT_APPLICATION Konzole . WriteLine ( "Vaši aplikaci již máme." ) Konec Vyberte stav případu . APARTMENT_RENTED Konzole . WriteLine ( "Počkejte, pronajmeme vám byt." ) Konec Vybrat Konec Vybrat End Sub Public Sub CheckApplication () Dim yesNo = _random . [ Další ] () Mod 10 Vyberte Case _state Case State . Konzole FULLY_RENTED . WriteLine ( "Omlouváme se, jsme plně pronajati." ) Ukončit Select Case State . WAITING Console . WriteLine ( "Musíte podat přihlášku." ) Ukončit Vyberte stav případu . GOT_APPLICATION Pokud anoNe > 4 AndAlso _numberApartments > 0 Pak Konzole . WriteLine ( "Blahopřejeme, byli jste schváleni." ) _state = State . APARTMENT_RENTED RentApartment () Jinak konzole . WriteLine ( "Je nám líto, nebyli jste schváleni." ) _state = State . WAITING End If Exit Vyberte Case State . APARTMENT_RENTED Konzole . WriteLine ( "Počkejte, pronajmeme vám byt." ) Konec Vybrat Konec Vybrat End Sub Public Sub RentApartment () Vyberte Case _state Case State . Konzole FULLY_RENTED . WriteLine ( "Omlouváme se, jsme plně pronajati." ) Ukončit Select Case State . WAITING Console . WriteLine ( "Musíte podat přihlášku." ) Ukončit Vyberte stav případu . GOT_APPLICATION Konzole . WriteLine ( "Musíte mít svou aplikaci zkontrolovanou." ) Konec Vyberte stav případu . APARTMENT_RENTED Konzole . WriteLine ( "Pronájem bytu......" ) _numberApartments -= 1 DispenseKeys () Konec Vybrat Konec Vybrat konec sub Public Sub DispenseKeys () Vyberte Case _state Case State . Konzole FULLY_RENTED . WriteLine ( "Omlouváme se, jsme plně pronajati." ) Ukončit Select Case State . WAITING Console . WriteLine ( "Musíte podat přihlášku." ) Ukončit Vyberte stav případu . GOT_APPLICATION Konzole . WriteLine ( "Musíte mít svou aplikaci zkontrolovanou." ) Konec Vyberte stav případu . APARTMENT_RENTED Konzole . WriteLine ( "Tady jsou vaše klíče!" ) _state = State . WAITING Konec Vybrat Konec Vybrat End Sub End Class třídní program Sdílená dílčí hlavní () Dim rentMethods = nové RentalMethods ( 9 ) metody pronájmu . Metody pronájmu GetApplication () . CheckApplication () rentMethods . PronájemApartment () metody pronájmu . DispenseKeys () Konzole . Přečíst () End Sub End Class End Namespace


Příklad PHP5

Zdrojový text v jazyce php5 <?php /** * Vzor Stav řídí, jak se změní chování objektu, když se změní jeho vnitřní stav. * Navenek to vypadá, že objekt změní svou třídu. */ jmenný prostor state1 { class Client { public function __construct () { $context = new Context (); $kontext -> požadavek (); $kontext -> požadavek (); $kontext -> požadavek (); $kontext -> požadavek (); $kontext -> požadavek (); $kontext -> požadavek (); } } class Test { public static function go () { $client = new Client (); } } /** * Třída s více vnitřními stavy */ class Context { /** * @var ASTate */ public $state ; const STATE_A = 1 ; const STATE_B = 2 ; const STATE_C = 3 ; public function __construct () { $this -> setState ( Context :: STATE_A ); } /** * Kontextové akce jsou delegovány na stavové objekty pro zpracování */ public function request () { $this -> state -> handle (); } /** * Toto je jeden způsob, jak implementovat přepínání stavu * @param $state je vybraný stav, možné možnosti jsou uvedeny v seznamu konstant Context::STATE_.. */ public function setState ( $state ) { if ( $ stav == Kontext :: STATE_A ) { $this -> stav = new ConcreteStateA ( $this ); } elseif ( $stav == Kontext :: STATE_B ) { $this -> stav = new ConcreteStateB ( $this ); } elseif ( $stav == Kontext :: STATE_C ) { $this -> stav = new ConcreteStateC ( $this ); } } } /** * Společné rozhraní pro všechny konkrétní stavy. * Všechny stavy implementují stejné rozhraní a jsou proto zaměnitelné. */ class AState { /** * @var Kontextové uložení odkazu na kontext pro pohodlné přepínání stavu */ protected $context ; public function __construct ( $kontext ) { $toto -> kontext = $kontext ; } /** * Zpracování v různých stavech se může lišit. * Pokud ASTate není jen rozhraní, ale abstraktní třída, * pak může obsahovat standardní zpracování, pak třídy konkrétních stavů budou popisovat pouze své vlastnosti týkající se standardního chování. */ public function handle () { echo " \n standardní handle" ; } } /** * Dále následuje sada specifických stavů, které zpracovávají požadavky z Kontextu. * Každá třída poskytuje vlastní implementaci požadavku. * Když tedy objekt Context přejde do jiného stavu, změní se také jeho chování. */ class ConcreteStateA extends AState { public function handle () { echo " \n State A handle" ; // přepnutí stavu $this -> context -> setState ( Context :: STATE_B ); } } class ConcreteStateB extends AState { public function handle () { echo " \n State B handle" ; // přepnout stav $this -> context -> setState ( Context :: STATE_C ); } } class ConcreteStateC extends AState { public function handle () { echo " \n State C handle" ; // přepnutí stavu $this -> context -> setState ( Context :: STATE_A ); } } test :: jít (); } Příklad s automatem ze vzorů head first v php5 <?php /** * Konkrétnější příklad založený na vzoru "State". * Vzor Stav řídí, jak se změní chování objektu, když se změní jeho vnitřní stav. * Navenek to vypadá, že objekt změní svou třídu. */ jmenný prostor state2 { class Client { public function __construct () { $context = new Context (); $kontext -> dispense (); $kontext -> insertQuarter (); $context -> turnCrank (); $kontext -> insertQuarter (); $context -> turnCrank (); $kontext -> insertQuarter (); $context -> turnCrank (); } } class Test { public static function go () { $client = new Client (); } } /** * Třída s více vnitřními stavy */ class Context { /** * @var ASTate */ public $state ; /** * Možné stavy */ const STATE_SOLD_OUT = 1 ; const STATE_NO_QUARTER_STATE = 2 ; const STATE_HAS_QUARTER_STATE = 3 ; const STATE_SOLD_STATE = 4 ; const STATE_WINNER_STATE = 5 ; /** * @var int Kolik žvýkačky je ve stroji? */ public $count = 2 ; public function __construct () { $this -> setState ( Context :: STATE_NO_QUARTER_STATE ); } /** * Kontextové akce jsou delegovány na stavové objekty pro zpracování */ public function insertQuarter () { $this -> state -> insertQuarter (); } public function ejectQuarter () { $this -> stav -> ejectQuarter (); } public function turnCrank () { $this -> state -> turnCrank (); $this -> state -> dispense (); } veřejná funkce výdej () { $this -> stav -> výdej (); } /** * Toto je jeden způsob, jak implementovat přepínání stavu * @param $state je vybraný stav, možné možnosti jsou uvedeny v seznamu konstant Context::STATE_.. */ public function setState ( $state ) { if ( $ state == Kontext :: STATE_SOLD_OUT ) { $this -> state = new ConcreteStateSoldOut ( $this ); } elseif ( $stav == Kontext :: STATE_NO_QUARTER_STATE ) { $this -> stav = new ConcreteStateNoQuarter ( $this ); } elseif ( $stav == Kontext :: STATE_HAS_QUARTER_STATE ) { $this -> stav = new ConcreteStateHasQuarter ( $this ); } elseif ( $state == Context :: STATE_SOLD_STATE ) { $this -> state = new ConcreteStateSoldState ( $this ); } elseif ( $state == Context :: STATE_WINNER_STATE ) { $this -> state = new ConcreteStateWinnerState ( $this ); } } public function releaseBall () { if ( $this -> count > 0 ) { echo "Míček uvolněn" ; $toto -> pocet -= 1 ; } else { echo "Žádné koule k vypuštění :(" ; } } } /** * Společné rozhraní pro všechny konkrétní stavy. * Všechny stavy implementují stejné rozhraní a jsou proto zaměnitelné. */ class AState { /** * @var Kontextové uložení odkazu na kontext pro pohodlné přepínání stavu */ protected $context ; public function __construct ( & $context ) { $this -> context =& $context ; } /** * Zpracování v různých stavech se může lišit. * Pokud ASTate není jen rozhraní, ale abstraktní třída, * pak může obsahovat standardní zpracování, pak třídy konkrétních stavů budou popisovat pouze své vlastnosti týkající se standardního chování. */ public function insertQuarter () { echo " \n lol, to nemůžeš" ; } public function ejectQuarter () { echo " \n lol, to nemůžeš" ; } public function turnCrank () { echo " \n lol, to nemůžeš" ; } public function dispense () { echo " \n lol, to nemůžete udělat" ; } } /** * Dále následuje sada specifických stavů, které zpracovávají požadavky z Kontextu. * Každá třída poskytuje vlastní implementaci požadavku. * Když tedy objekt Context přejde do jiného stavu, změní se také jeho chování. */ class ConcreteStateSoldOut rozšiřuje AState { public function insertQuarter () { echo " \n promiň, mám vyprodáno, nemůžu zabrat čtvrtky" ; } } class ConcreteStateNoQuarter extends AState { public function insertQuarter () { echo " \n dostal čtvrtinu, jo!" ; // přepnutí stavu $this -> context -> setState ( Context :: STATE_HAS_QUARTER_STATE ); } } class ConcreteStateHasQuarter extends AState { public function ejectQuarter () { echo " \n vezměte si své peníze zpět" ; // přepnout stav $this -> context -> setState ( Context :: STATE_NO_QUARTER_STATE ); } public function turnCrank () { echo " \n otočili jste se" ; $vítěz = rand ( 1 , 10 ) == 10 ? 1 : 0 ; if ( $winner ) { $this -> context -> setState ( Context :: STATE_WINNER_STATE ); } else { $this -> context -> setState ( Context :: STATE_SOLD_STATE ); } } } class ConcreteStateSoldState rozšiřuje AState { veřejná funkce výdej () { echo " \n výdej, jo!" ; $this -> kontext -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Context :: STATE_SOLD_OUT ); } else { // přepnout stav $this -> context -> setState ( Context :: STATE_NO_QUARTER_STATE ); } } } class ConcreteStateWinnerState rozšiřuje AState { veřejná funkce výdej () { echo " \n výdej, jo!" ; $this -> kontext -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Context :: STATE_SOLD_OUT ); } else { echo " \n ps jste VÍTĚZ, dostanete míč navíc!" ; $this -> kontext -> releaseBall (); if ( $this -> context -> count == 0 ) { $this -> context -> setState ( Context :: STATE_SOLD_OUT ); } else { $this -> context -> setState ( Context :: STATE_NO_QUARTER_STATE ); } } } } test :: jít (); }