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í.
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 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 > StateAZmě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 );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 ( Já ) _gotApplicationState = New GotApplicationState ( Já ) _apartmentRentedState = Nový ApartmentRentedState ( Já ) _fullRentedState = SubState New ( Já ) _ _ _ _ _ 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 NamespaceStejný 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
Designové vzory | |
---|---|
Hlavní | |
Generativní | |
Strukturální | |
Behaviorální | |
Paralelní programování |
|
architektonický |
|
Java EE šablony | |
Jiné šablony | |
knihy | |
Osobnosti |