Состояние (англ.State) — поведенческийшаблон проектирования. Используется в тех случаях, когда во время выполнения программы объект должен менять своё поведение в зависимости от своего состояния.
Паттерн состоит из 3 блоков:
Widget — класс, объекты которого должны менять своё поведение в зависимости от состояния.
IState — интерфейс, который должен реализовать каждое из конкретных состояний. Через этот интерфейс объект Widget взаимодействует с состоянием, делегируя ему вызовы методов. Интерфейс должен содержать средства для обратной связи с объектом, поведение которого нужно изменить. Для этого используется событие (паттерн Publisher — Subscriber). Это необходимо для того, чтобы в процессе выполнения программы заменять объект состояния при появлении событий. Возможны случаи, когда сам Widget периодически опрашивает объект состояния на наличие перехода.
StateA … StateZ — классы конкретных состояний. Должны содержать информацию о том, при каких условиях и в какие состояния может переходить объект из текущего состояния. Например, из StateA объект может переходить в состояние StateB и StateC, а из StateB — обратно в StateA и так далее. Объект одного из них должен содержать Widget при создании.
Применение данного паттерна может быть затруднено, если состояния должны обмениваться данными, или одно состояние настраивает свойства другого. В этом случае понадобится глобальный объект, что не очень хорошее архитектурное решение.
#pragma once#include<string>#include<iostream>classState;classStateContext;classSolidState;classLiquidState;classGasState;classState{std::stringname;public:State(conststd::string&name):name(name){}std::stringGetName(){returnname;}virtualvoidFreeze(StateContext*)=0;virtualvoidHeat(StateContext*)=0;};classStateContext{private:State*state;public:StateContext(State*state):state(state){}voidFreeze(){std::cout<<"Freezing "<<state->GetName()<<"..."<<std::endl;state->Freeze(this);}voidHeat(){std::cout<<"Heating "<<state->GetName()<<"..."<<std::endl;state->Heat(this);}voidSetState(State*s){std::cout<<"Changing state from "<<state->GetName()<<" to "<<s->GetName()<<"..."<<std::endl;deletestate;state=s;}State*GetState(){returnstate;}~StateContext(){deletestate;}};classSolidState:publicState{public:SolidState():State("Solid"){}virtualvoidFreeze(StateContext*state);virtualvoidHeat(StateContext*state);};classLiquidState:publicState{public:LiquidState():State("Liquid"){}virtualvoidFreeze(StateContext*state);virtualvoidHeat(StateContext*state);};classGasState:publicState{public:GasState():State("Gas"){}virtualvoidFreeze(StateContext*state);virtualvoidHeat(StateContext*state);};voidSolidState::Freeze(StateContext*state){std::cout<<"Nothing happens"<<std::endl;}voidSolidState::Heat(StateContext*state){state->SetState(newLiquidState());}voidLiquidState::Freeze(StateContext*state){state->SetState(newSolidState());}voidLiquidState::Heat(StateContext*state){state->SetState(newGasState());}voidGasState::Freeze(StateContext*state){state->SetState(newLiquidState());}voidGasState::Heat(StateContext*state){std::cout<<"Nothing happens"<<std::endl;}voidTest(){StateContext*sc=newStateContext(newSolidState());sc->Heat();sc->Heat();sc->Heat();sc->Freeze();sc->Freeze();sc->Freeze();deletesc;}
usingSystem;namespaceDigital_Patterns.Behavioral.State{publicinterfaceIAutomatState{StringGotApplication();StringCheckApplication();StringRentApartment();StringDispenseKeys();}publicinterfaceIAutomat{voidGotApplication();voidCheckApplication();voidRentApartment();voidSetState(IAutomatStates);IAutomatStateGetWaitingState();IAutomatStateGetGotApplicationState();IAutomatStateGetApartmentRentedState();IAutomatStateGetFullyRentedState();Int32Count{get;set;}}publicclassAutomat:IAutomat{privateIAutomatState_waitingState;privateIAutomatState_gotApplicationState;privateIAutomatState_apartmentRentedState;privateIAutomatState_fullyRentedState;privateIAutomatState_state;privateInt32_count;publicAutomat(Int32n){_count=n;_waitingState=newWaitingState(this);_gotApplicationState=newGotApplicationState(this);_apartmentRentedState=newApartmentRentedState(this);_fullyRentedState=newFullyRentedState(this);_state=_waitingState;}publicvoidGotApplication(){Console.WriteLine(_state.GotApplication());}publicvoidCheckApplication(){Console.WriteLine(_state.CheckApplication());}publicvoidRentApartment(){Console.WriteLine(_state.RentApartment());Console.WriteLine(_state.DispenseKeys());}publicvoidSetState(IAutomatStates){_state=s;}publicIAutomatStateGetWaitingState(){return_waitingState;}publicIAutomatStateGetGotApplicationState(){return_gotApplicationState;}publicIAutomatStateGetApartmentRentedState(){return_apartmentRentedState;}publicIAutomatStateGetFullyRentedState(){return_fullyRentedState;}publicintCount{get{return_count;}set{_count=value;}}}publicclassWaitingState:IAutomatState{privateAutomat_automat;publicWaitingState(Automatautomat){_automat=automat;}publicStringGotApplication(){_automat.SetState(_automat.GetGotApplicationState());return"Thanks for the application.";}publicStringCheckApplication(){return"You have to submit an application.";}publicStringRentApartment(){return"You have to submit an application.";}publicStringDispenseKeys(){return"You have to submit an application.";}}publicclassGotApplicationState:IAutomatState{privateAutomat_automat;privatereadonlyRandom_random;publicGotApplicationState(Automatautomat){_automat=automat;_random=newRandom(System.DateTime.Now.Millisecond);}publicStringGotApplication(){return"We already got your application.";}publicStringCheckApplication(){varyesNo=_random.Next()%10;if(yesNo>4&&_automat.Count>0){_automat.SetState(_automat.GetApartmentRentedState());return"Congratulations, you were approved.";}else{_automat.SetState(_automat.GetWaitingState());return"Sorry, you were not approved.";}}publicStringRentApartment(){return"You must have your application checked.";}publicStringDispenseKeys(){return"You must have your application checked.";}}publicclassApartmentRentedState:IAutomatState{privateAutomat_automat;publicApartmentRentedState(Automatautomat){_automat=automat;}publicStringGotApplication(){return"Hang on, we'ra renting you an apartmeny.";}publicStringCheckApplication(){return"Hang on, we'ra renting you an apartmeny.";}publicStringRentApartment(){_automat.Count=_automat.Count-1;return"Renting you an apartment....";}publicStringDispenseKeys(){if(_automat.Count<=0)_automat.SetState(_automat.GetFullyRentedState());else_automat.SetState(_automat.GetWaitingState());return"Here are your keys!";}}publicclassFullyRentedState:IAutomatState{privateAutomat_automat;publicFullyRentedState(Automatautomat){_automat=automat;}publicStringGotApplication(){return"Sorry, we're fully rented.";}publicStringCheckApplication(){return"Sorry, we're fully rented.";}publicStringRentApartment(){return"Sorry, we're fully rented.";}publicStringDispenseKeys(){return"Sorry, we're fully rented.";}}classProgram{staticvoidMain(string[]args){varautomat=newAutomat(9);automat.GotApplication();automat.CheckApplication();automat.RentApartment();}}}
usingSystem;namespaceDigital_Patterns.Behavioral.State{publicenumState{FULLY_RENTED=0,WAITING=1,GOT_APPLICATION=2,APARTMENT_RENTED=3,}publicclassRentalMethods{privatereadonlyRandom_random;privateInt32_numberApartments;privateState_state=State.WAITING;publicRentalMethods(Int32n){_numberApartments=n;_random=newRandom(System.DateTime.Now.Millisecond);}publicvoidGetApplication(){switch(_state){caseState.FULLY_RENTED:Console.WriteLine("Sorry, we're fully rented.");break;caseState.WAITING:_state=State.GOT_APPLICATION;Console.WriteLine("Thanks for the application.");break;caseState.GOT_APPLICATION:Console.WriteLine("We already got your application.");break;caseState.APARTMENT_RENTED:Console.WriteLine("Hang on, we'ra renting you an apartment.");break;}}publicvoidCheckApplication(){varyesNo=_random.Next()%10;switch(_state){caseState.FULLY_RENTED:Console.WriteLine("Sorry, we're fully rented.");break;caseState.WAITING:Console.WriteLine("You have to submit an application.");break;caseState.GOT_APPLICATION:if(yesNo>4&&_numberApartments>0){Console.WriteLine("Congratulations, you were approved.");_state=State.APARTMENT_RENTED;RentApartment();}else{Console.WriteLine("Sorry, you were not approved.");_state=State.WAITING;}break;caseState.APARTMENT_RENTED:Console.WriteLine("Hang on, we'ra renting you an apartment.");break;}}publicvoidRentApartment(){switch(_state){caseState.FULLY_RENTED:Console.WriteLine("Sorry, we're fully rented.");break;caseState.WAITING:Console.WriteLine("You have to submit an application.");break;caseState.GOT_APPLICATION:Console.WriteLine("You must have your application checked.");break;caseState.APARTMENT_RENTED:Console.WriteLine("Renting you an apartment....");_numberApartments--;DispenseKeys();break;}}publicvoidDispenseKeys(){switch(_state){caseState.FULLY_RENTED:Console.WriteLine("Sorry, we're fully rented.");break;caseState.WAITING:Console.WriteLine("You have to submit an application.");break;caseState.GOT_APPLICATION:Console.WriteLine("You must have your application checked.");break;caseState.APARTMENT_RENTED:Console.WriteLine("Here are your keys!");_state=State.WAITING;break;}}}classProgram{staticvoidMain(string[]args){varrentalMethods=newRentalMethods(9);rentalMethods.GetApplication();rentalMethods.CheckApplication();rentalMethods.RentApartment();rentalMethods.DispenseKeys();}}}
publicclassStateExample{publicstaticvoidmain(String[]args){StateContextcontext=newStateContext();context.heat();context.heat();context.heat();context.freeze();context.freeze();context.freeze();// OUTPUT:// Heating solid substance...// Changing state to liquid...// Heating liquid substance...// Changing state to gaseous...// Heating gaseous substance...// Nothing happens.// Freezing gaseous substance...// Changing state to liquid...// Freezing liquid substance...// Changing state to solid...// Freezing solid substance...// Nothing happens.}}interfaceState{StringgetName();voidfreeze(StateContextcontext);voidheat(StateContextcontext);}classSolidStateimplementsState{privatestaticfinalStringNAME="solid";publicStringgetName(){returnNAME;}publicvoidfreeze(StateContextcontext){System.out.println("Nothing happens.");}publicvoidheat(StateContextcontext){context.setState(newLiquidState());}}classLiquidStateimplementsState{privatestaticfinalStringNAME="liquid";publicStringgetName(){returnNAME;}publicvoidfreeze(StateContextcontext){context.setState(newSolidState());}publicvoidheat(StateContextcontext){context.setState(newGaseousState());}}classGaseousStateimplementsState{privatestaticfinalStringNAME="gaseous";publicStringgetName(){returnNAME;}publicvoidfreeze(StateContextcontext){context.setState(newLiquidState());}publicvoidheat(StateContextcontext){System.out.println("Nothing happens.");}}classStateContext{privateStatestate=newSolidState();publicvoidfreeze(){System.out.println("Freezing "+state.getName()+" substance...");state.freeze(this);}publicvoidheat(){System.out.println("Heating "+state.getName()+" substance...");state.heat(this);}publicvoidsetState(Statestate){System.out.println("Changing state to "+state.getName()+"...");this.state=state;}publicStategetState(){returnstate;}}
fromabcimportABCMeta,abstractmethodclassState(metaclass=ABCMeta):@abstractmethoddefeat(self)->str:pass@abstractmethoddeffind_food(self)->str:pass@abstractmethoddefmove(self)->str:pass@abstractmethoddefdream(self)->str:passclassSleepState(State):defeat(self)->str:return'не может есть, пока спит'deffind_food(self)->str:return'ищет еду, но только в своих мечтах'defmove(self)->str:return'не может двигаться, пока спит'defdream(self)->str:return'спит и видит чудный сон'classOnGroundState(State):defeat(self)->str:return'вываливает на пузо добытых моллюсков и начинает неспешно их есть'deffind_food(self)->str:return'находит дурно пахнущую, но вполне съедобную тушу выбросившегося на берег кита'defmove(self)->str:return'неуклюже ползет вдоль береговой линии'defdream(self)->str:return'на мгновние останавливается, замечтавшись об одной знакомой самке'classInWaterState(State):defeat(self)->str:return'не может есть в воде'deffind_food(self)->str:return'вспахивает бивнями морское дно, вылавливая моллюсков своими вибриссами'defmove(self)->str:return'грациозно рассекает волны мирового океана'defdream(self)->str:return'не спит и не мечтает в воде - это слишком сложно'classWalrus:def__init__(self,state:State)->None:self._state=statedefchange_state(self,state:State)->None:self._state=statedefeat(self)->None:self._execute('eat')deffind_food(self)->None:self._execute('find_food')defmove(self)->None:self._execute('move')defdream(self)->None:self._execute('dream')def_execute(self,operation:str)->None:try:func=getattr(self._state,operation)print('Морж {}.'.format(func()))exceptAttributeError:print('Морж такого делать не умеет.')if__name__=='__main__':sleep=SleepState()on_ground=OnGroundState()in_water=InWaterState()walrus=Walrus(on_ground)print('OUTPUT:')walrus.change_state(in_water)walrus.move()walrus.find_food()walrus.change_state(on_ground)walrus.eat()walrus.move()walrus.dream()walrus.change_state(sleep)walrus.dream()'''OUTPUT:Морж грациозно рассекает волны мирового океана.Морж вспахивает бивнями морское дно, вылавливая моллюсков своими вибриссами.Морж вываливает на пузо добытых моллюсков и начинает неспешно их есть.Морж неуклюже ползет вдоль береговой линии.Морж на мгновние останавливается, замечтавшись об одной знакомой самке.Морж спит и видит чудный сон.'''
NamespaceDigital_Patterns.Behavioral.StatePublicInterfaceIAutomatStateFunctionGotApplication()As[String]FunctionCheckApplication()As[String]FunctionRentApartment()As[String]FunctionDispenseKeys()As[String]EndInterfacePublicInterfaceIAutomatSubGotApplication()SubCheckApplication()SubRentApartment()SubSetState(ByValsAsIAutomatState)FunctionGetWaitingState()AsIAutomatStateFunctionGetGotApplicationState()AsIAutomatStateFunctionGetApartmentRentedState()AsIAutomatStateFunctionGetFullyRentedState()AsIAutomatStatePropertyCount()AsInt32EndInterfacePublicClassAutomatImplementsIAutomatPrivate_waitingStateAsIAutomatStatePrivate_gotApplicationStateAsIAutomatStatePrivate_apartmentRentedStateAsIAutomatStatePrivate_fullyRentedStateAsIAutomatStatePrivate_stateAsIAutomatStatePrivate_countAsInt32PublicSubNew(ByValnAsInt32)_count=n_waitingState=NewWaitingState(Me)_gotApplicationState=NewGotApplicationState(Me)_apartmentRentedState=NewApartmentRentedState(Me)_fullyRentedState=NewFullyRentedState(Me)_state=_waitingStateEndSubPublicSubGotApplication()ImplementsIAutomat.GotApplicationConsole.WriteLine(_state.GotApplication())EndSubPublicSubCheckApplication()ImplementsIAutomat.CheckApplicationConsole.WriteLine(_state.CheckApplication())EndSubPublicSubRentApartment()ImplementsIAutomat.RentApartmentConsole.WriteLine(_state.RentApartment())Console.WriteLine(_state.DispenseKeys())EndSubPublicSubSetState(ByValsAsIAutomatState)ImplementsIAutomat.SetState_state=sEndSubPublicFunctionGetWaitingState()AsIAutomatStateImplementsIAutomat.GetWaitingStateReturn_waitingStateEndFunctionPublicFunctionGetGotApplicationState()AsIAutomatStateImplementsIAutomat.GetGotApplicationStateReturn_gotApplicationStateEndFunctionPublicFunctionGetApartmentRentedState()AsIAutomatStateImplementsIAutomat.GetApartmentRentedStateReturn_apartmentRentedStateEndFunctionPublicFunctionGetFullyRentedState()AsIAutomatStateImplementsIAutomat.GetFullyRentedStateReturn_fullyRentedStateEndFunctionPublicPropertyCount()AsIntegerImplementsIAutomat.CountGetReturn_countEndGetSet(ByValvalueAsInteger)_count=valueEndSetEndPropertyEndClassPublicClassWaitingStateImplementsIAutomatStatePrivate_automatAsAutomatPublicSubNew(ByValautomatAsAutomat)_automat=automatEndSubPublicFunctionGotApplication()As[String]ImplementsIAutomatState.GotApplication_automat.SetState(_automat.GetGotApplicationState())Return"Thanks for the application."EndFunctionPublicFunctionCheckApplication()As[String]ImplementsIAutomatState.CheckApplicationReturn"You have to submit an application."EndFunctionPublicFunctionRentApartment()As[String]ImplementsIAutomatState.RentApartmentReturn"You have to submit an application."EndFunctionPublicFunctionDispenseKeys()As[String]ImplementsIAutomatState.DispenseKeysReturn"You have to submit an application."EndFunctionEndClassPublicClassGotApplicationStateImplementsIAutomatStatePrivate_automatAsAutomatPrivateReadOnly_randomAsRandomPublicSubNew(ByValautomatAsAutomat)_automat=automat_random=NewRandom(System.DateTime.Now.Millisecond)EndSubPublicFunctionGotApplication()As[String]ImplementsIAutomatState.GotApplicationReturn"We already got your application."EndFunctionPublicFunctionCheckApplication()As[String]ImplementsIAutomatState.CheckApplicationDimyesNo=_random.[Next]()Mod10IfyesNo>4AndAlso_automat.Count>0Then_automat.SetState(_automat.GetApartmentRentedState())Return"Congratulations, you were approved."Else_automat.SetState(_automat.GetWaitingState())Return"Sorry, you were not approved."EndIfEndFunctionPublicFunctionRentApartment()As[String]ImplementsIAutomatState.RentApartmentReturn"You must have your application checked."EndFunctionPublicFunctionDispenseKeys()As[String]ImplementsIAutomatState.DispenseKeysReturn"You must have your application checked."EndFunctionEndClassPublicClassApartmentRentedStateImplementsIAutomatStatePrivate_automatAsAutomatPublicSubNew(ByValautomatAsAutomat)_automat=automatEndSubPublicFunctionGotApplication()As[String]ImplementsIAutomatState.GotApplicationReturn"Hang on, we'ra renting you an apartmeny."EndFunctionPublicFunctionCheckApplication()As[String]ImplementsIAutomatState.CheckApplicationReturn"Hang on, we'ra renting you an apartmeny."EndFunctionPublicFunctionRentApartment()As[String]ImplementsIAutomatState.RentApartment_automat.Count=_automat.Count-1Return"Renting you an apartment...."EndFunctionPublicFunctionDispenseKeys()As[String]ImplementsIAutomatState.DispenseKeysIf_automat.Count<=0Then_automat.SetState(_automat.GetFullyRentedState())Else_automat.SetState(_automat.GetWaitingState())EndIfReturn"Here are your keys!"EndFunctionEndClassPublicClassFullyRentedStateImplementsIAutomatStatePrivate_automatAsAutomatPublicSubNew(ByValautomatAsAutomat)_automat=automatEndSubPublicFunctionGotApplication()As[String]ImplementsIAutomatState.GotApplicationReturn"Sorry, we're fully rented."EndFunctionPublicFunctionCheckApplication()As[String]ImplementsIAutomatState.CheckApplicationReturn"Sorry, we're fully rented."EndFunctionPublicFunctionRentApartment()As[String]ImplementsIAutomatState.RentApartmentReturn"Sorry, we're fully rented."EndFunctionPublicFunctionDispenseKeys()As[String]ImplementsIAutomatState.DispenseKeysReturn"Sorry, we're fully rented."EndFunctionEndClassClassProgramSharedSubMain()Dimautomat=NewAutomat(9)automat.GotApplication()automat.CheckApplication()automat.RentApartment()Console.Read()EndSubEndClassEndNamespace
Тот же пример, без применения шаблона
Исходный текст на языке VB.NET
NamespaceDigital_Patterns.Behavioral.StatePublicEnumStateFULLY_RENTED=0WAITING=1GOT_APPLICATION=2APARTMENT_RENTED=3EndEnumPublicClassRentalMethodsPrivateReadOnly_randomAsRandomPrivate_numberApartmentsAsInt32Private_stateAsState=State.WAITINGPublicSubNew(ByValnAsInt32)_numberApartments=n_random=NewRandom(System.DateTime.Now.Millisecond)EndSubPublicSubGetApplication()SelectCase_stateCaseState.FULLY_RENTEDConsole.WriteLine("Sorry, we're fully rented.")ExitSelectCaseState.WAITING_state=State.GOT_APPLICATIONConsole.WriteLine("Thanks for the application.")ExitSelectCaseState.GOT_APPLICATIONConsole.WriteLine("We already got your application.")ExitSelectCaseState.APARTMENT_RENTEDConsole.WriteLine("Hang on, we'ra renting you an apartmeny.")ExitSelectEndSelectEndSubPublicSubCheckApplication()DimyesNo=_random.[Next]()Mod10SelectCase_stateCaseState.FULLY_RENTEDConsole.WriteLine("Sorry, we're fully rented.")ExitSelectCaseState.WAITINGConsole.WriteLine("You have to submit an application.")ExitSelectCaseState.GOT_APPLICATIONIfyesNo>4AndAlso_numberApartments>0ThenConsole.WriteLine("Congratulations, you were approved.")_state=State.APARTMENT_RENTEDRentApartment()ElseConsole.WriteLine("Sorry, you were not approved.")_state=State.WAITINGEndIfExitSelectCaseState.APARTMENT_RENTEDConsole.WriteLine("Hang on, we'ra renting you an apartmeny.")ExitSelectEndSelectEndSubPublicSubRentApartment()SelectCase_stateCaseState.FULLY_RENTEDConsole.WriteLine("Sorry, we're fully rented.")ExitSelectCaseState.WAITINGConsole.WriteLine("You have to submit an application.")ExitSelectCaseState.GOT_APPLICATIONConsole.WriteLine("You must have your application checked.")ExitSelectCaseState.APARTMENT_RENTEDConsole.WriteLine("Renting you an apartment....")_numberApartments-=1DispenseKeys()ExitSelectEndSelectEndSubPublicSubDispenseKeys()SelectCase_stateCaseState.FULLY_RENTEDConsole.WriteLine("Sorry, we're fully rented.")ExitSelectCaseState.WAITINGConsole.WriteLine("You have to submit an application.")ExitSelectCaseState.GOT_APPLICATIONConsole.WriteLine("You must have your application checked.")ExitSelectCaseState.APARTMENT_RENTEDConsole.WriteLine("Here are your keys!")_state=State.WAITINGExitSelectEndSelectEndSubEndClassClassProgramSharedSubMain()DimrentalMethods=NewRentalMethods(9)rentalMethods.GetApplication()rentalMethods.CheckApplication()rentalMethods.RentApartment()rentalMethods.DispenseKeys()Console.Read()EndSubEndClassEndNamespace
<?php/** * Паттерн Состояние управляет изменением поведения объекта при изменении его внутреннего состояния. * Внешне это выглядит так, словно объект меняет свой класс. */namespacestate1{classClient{publicfunction__construct(){$context=newContext();$context->request();$context->request();$context->request();$context->request();$context->request();$context->request();}}classTest{publicstaticfunctiongo(){$client=newClient();}}/** * Класс с несколькими внутренними состояниями */classContext{/** * @var AState */public$state;constSTATE_A=1;constSTATE_B=2;constSTATE_C=3;publicfunction__construct(){$this->setState(Context::STATE_A);}/** * Действия Context делегируются объектам состояний для обработки */publicfunctionrequest(){$this->state->handle();}/** * Это один из способов реализации переключения состояний * @param $state выбранное состояние, возможные варианты перечислены в списке констант Context::STATE_.. */publicfunctionsetState($state){if($state==Context::STATE_A){$this->state=newConcreteStateA($this);}elseif($state==Context::STATE_B){$this->state=newConcreteStateB($this);}elseif($state==Context::STATE_C){$this->state=newConcreteStateC($this);}}}/** * Общий интерфейс всех конкретных состояний. * Все состояния реализуют один интерфейс, а следовтельно, являются взаимозаменяемыми. */classAState{/** * @var Context храним ссылку на контекст для удобного переключения состояний */protected$context;publicfunction__construct($context){$this->context=$context;}/** * Обработка в разных состояниях может отличаться. * Если AState не просто интерфейс а абстрактный класс, * то он может содержать стандартные обработки, тогда классы конкретных состояний будут описывать только свои особенности относительно стандартного поведения. */publicfunctionhandle(){echo"\n standart handle";}}/** * Далее идёт набор конкретных состояний, которые обрабатывают запросы от Context. * Каждый класс предоставляет собственную реализацию запроса. * Таким образом, при переходе объекта Context в другое состояние, меняется и его поведение. */classConcreteStateAextendsAState{publicfunctionhandle(){echo"\n State A handle";// переключаем состояние$this->context->setState(Context::STATE_B);}}classConcreteStateBextendsAState{publicfunctionhandle(){echo"\n State B handle";// переключаем состояние$this->context->setState(Context::STATE_C);}}classConcreteStateCextendsAState{publicfunctionhandle(){echo"\n State C handle";// переключаем состояние$this->context->setState(Context::STATE_A);}}Test::go();}
Пример с автоматом из head first patterns на языке php5
<?php/** * Более конкретный пример на основе паттерна "Состояние". * Паттерн Состояние управляет изменением поведения объекта при изменении его внутреннего состояния. * Внешне это выглядит так, словно объект меняет свой класс. */namespacestate2{classClient{publicfunction__construct(){$context=newContext();$context->dispense();$context->insertQuarter();$context->turnCrank();$context->insertQuarter();$context->turnCrank();$context->insertQuarter();$context->turnCrank();}}classTest{publicstaticfunctiongo(){$client=newClient();}}/** * Класс с несколькими внутренними состояниями */classContext{/** * @var AState */public$state;/** * Возможные состояния */constSTATE_SOLD_OUT=1;constSTATE_NO_QUARTER_STATE=2;constSTATE_HAS_QUARTER_STATE=3;constSTATE_SOLD_STATE=4;constSTATE_WINNER_STATE=5;/** * @var int Сколько жвачки в автомате? */public$count=2;publicfunction__construct(){$this->setState(Context::STATE_NO_QUARTER_STATE);}/** * Действия Context делегируются объектам состояний для обработки */publicfunctioninsertQuarter(){$this->state->insertQuarter();}publicfunctionejectQuarter(){$this->state->ejectQuarter();}publicfunctionturnCrank(){$this->state->turnCrank();$this->state->dispense();}publicfunctiondispense(){$this->state->dispense();}/** * Это один из способов реализации переключения состояний * @param $state выбранное состояние, возможные варианты перечислены в списке констант Context::STATE_.. */publicfunctionsetState($state){if($state==Context::STATE_SOLD_OUT){$this->state=newConcreteStateSoldOut($this);}elseif($state==Context::STATE_NO_QUARTER_STATE){$this->state=newConcreteStateNoQuarter($this);}elseif($state==Context::STATE_HAS_QUARTER_STATE){$this->state=newConcreteStateHasQuarter($this);}elseif($state==Context::STATE_SOLD_STATE){$this->state=newConcreteStateSoldState($this);}elseif($state==Context::STATE_WINNER_STATE){$this->state=newConcreteStateWinnerState($this);}}publicfunctionreleaseBall(){if($this->count>0){echo"Ball released";$this->count-=1;}else{echo"No balls to release :(";}}}/** * Общий интерфейс всех конкретных состояний. * Все состояния реализуют один интерфейс, а следовтельно, являются взаимозаменяемыми. */classAState{/** * @var Context храним ссылку на контекст для удобного переключения состояний */protected$context;publicfunction__construct(&$context){$this->context=&$context;}/** * Обработка в разных состояниях может отличаться. * Если AState не просто интерфейс а абстрактный класс, * то он может содержать стандартные обработки, тогда классы конкретных состояний будут описывать только свои особенности относительно стандартного поведения. */publicfunctioninsertQuarter(){echo"\n lol, you can't do that";}publicfunctionejectQuarter(){echo"\n lol, you can't do that";}publicfunctionturnCrank(){echo"\n lol, you can't do that";}publicfunctiondispense(){echo"\n lol, you can't do that";}}/** * Далее идёт набор конкретных состояний, которые обрабатывают запросы от Context. * Каждый класс предоставляет собственную реализацию запроса. * Таким образом, при переходе объекта Context в другое состояние, меняется и его поведение. */classConcreteStateSoldOutextendsAState{publicfunctioninsertQuarter(){echo"\n sorry, i'm sold out, can't take quarters";}}classConcreteStateNoQuarterextendsAState{publicfunctioninsertQuarter(){echo"\n got quarter, yeah!";// переключаем состояние$this->context->setState(Context::STATE_HAS_QUARTER_STATE);}}classConcreteStateHasQuarterextendsAState{publicfunctionejectQuarter(){echo"\n take your money back";// переключаем состояние$this->context->setState(Context::STATE_NO_QUARTER_STATE);}publicfunctionturnCrank(){echo"\n you turned";$winner=rand(1,10)==10?1:0;if($winner){$this->context->setState(Context::STATE_WINNER_STATE);}else{$this->context->setState(Context::STATE_SOLD_STATE);}}}classConcreteStateSoldStateextendsAState{publicfunctiondispense(){echo"\n dispensing, yeah!";$this->context->releaseBall();if($this->context->count==0){$this->context->setState(Context::STATE_SOLD_OUT);}else{// переключаем состояние$this->context->setState(Context::STATE_NO_QUARTER_STATE);}}}classConcreteStateWinnerStateextendsAState{publicfunctiondispense(){echo"\n dispensing, yeah!";$this->context->releaseBall();if($this->context->count==0){$this->context->setState(Context::STATE_SOLD_OUT);}else{echo"\n p.s. you are WINNER, you get extra ball!";$this->context->releaseBall();if($this->context->count==0){$this->context->setState(Context::STATE_SOLD_OUT);}else{$this->context->setState(Context::STATE_NO_QUARTER_STATE);}}}}Test::go();}
Badan Pengembangan dan Pembinaan BahasaGedung Pusat Bahasa di Rawamangun, JakartaInformasi lembagaKantor pusatJalan Daksinapati Barat IV, Rawamangun, Jakarta TimurPejabat eksekutifKepala, E. Aminudin AzizDepartemen indukKemendikbud RistekSitus webbadanbahasa.kemdikbud.go.id Badan Pengembangan dan Pembinaan Bahasa (sempat dikenal dengan nama Pusat Bahasa dan Badan Pengembangan Bahasa dan Perbukuan) adalah unsur penunjang di Kementerian Pendidikan dan Kebudayaan Republik Indonesia yang mempunya...
Boy G. SaktiLahirYandi Yasin4 Agustus 1966 (umur 57)Batusangkar, Sumatera BaratKebangsaanIndonesiaAlmamaterInstitut Kesenian JakartaPekerjaanKoreograferOrang tuaGusmiati Suid Yandi Yasin atau yang lebih dikenal dengan Boy G. Sakti (lahir 4 Agustus 1966) adalah salah seorang koreografer Indonesia. Boy mulai belajar menari sejak umur 17 tahun di Gumarang Sakti Dance Company, di bawah bimbingan ibunya, Gusmiati Suid. Disamping itu ia juga belajar secara formal di Institut Kesenian Jakarta ...
Museum 4 Juni六四紀念館Galeri sejarahDidirikan26 April 2014 (2014-04-26)LokasiNo. 10, Ngai Wong Commercial Building, 11–13 Mong Kok Rd, Mong Kok, Kowloon, Hong KongJenisPrivatePendiriAliansi Hong Kong dalam Mendukung Gerakan Demokrat Patriotik Tiongkok Museum 4 Juni Hanzi tradisional: 六四紀念館 Hanzi sederhana: 六四纪念馆 Alih aksara Mandarin - Hanyu Pinyin: Liù Sì Jìniànguǎn Yue (Kantonis) - Romanisasi Yale: Luhk sei géi nihm gún - Jyutping: Luk6 sei3 gei2 nim6 ...
Rhys IfansRhys Ifans, 2011LahirRhys Owain Evans22 Juli 1967 (umur 56)[1][2]Haverfordwest, Pembrokeshire, WalesPekerjaanAktor, Produser, MusisiTahun aktif1990–sekarang Rhys Ifans (r̥ɨːs ˈivans; Rhys Owain Evans;[3] lahir 22 Juni 1967)[3][4][5][6] adalah aktor, produser, dan musisi Welsh. Dia dikenal karena penggambaran karakter seperti Spike di Notting Hill, Jed Parry di Enduring Love, Bola mata Paul masuk Kevin & Per...
American sailor Michael SchoettlePersonal informationFull nameMichael Beaver SchoettleBornSeptember 7, 1936 (1936-09-07) (age 87)Sailing careerCollege team Yale University Medal record Men's sailing Representing the United States Olympic Games 1952 Helsinki 5.5 metre Michael Beaver Schoettle (born September 7, 1936) is an American sailor and Olympic Champion. He competed at the 1952 Summer Olympics in Helsinki and earned a gold medal as crew in the 5.5 metre class on...
Questa voce sull'argomento stagioni delle società calcistiche italiane è solo un abbozzo. Contribuisci a migliorarla secondo le convenzioni di Wikipedia. Segui i suggerimenti del progetto di riferimento. Voce principale: Alma Juventus Fano 1906. Società Polisportiva del Littorio Alma Juventus FanoStagione 1938-1939Sport calcio Squadra Fano Allenatore Italo Breviglieri Presidente Aldo Paolini Serie C6º posto nel girone eliminatorio F. 1937-1938 1939-1940 Si invita a seguire il m...
American sports cable television channel Television channel Universal SportsCountryUnited StatesBroadcast areaNationwideHeadquartersWoodland Hills, CaliforniaProgrammingLanguage(s)EnglishPicture format480i (SDTV)OwnershipOwner InterMedia Partners (92%) NBC Sports Group (8%) HistoryLaunched2006; 18 years ago (2006)ClosedNovember 16, 2015; 8 years ago (2015-11-16)Replaced byOlympic Channel (2017; Universal HD carried existing contracts between 2015–2017)For...
Pour les articles homonymes, voir Schinkel. Si ce bandeau n'est plus pertinent, retirez-le. Cliquez ici pour en savoir plus. Cet article ne cite pas suffisamment ses sources (août 2021). Si vous disposez d'ouvrages ou d'articles de référence ou si vous connaissez des sites web de qualité traitant du thème abordé ici, merci de compléter l'article en donnant les références utiles à sa vérifiabilité et en les liant à la section « Notes et références ». En pratique...
Державний комітет телебачення і радіомовлення України (Держкомтелерадіо) Приміщення комітетуЗагальна інформаціяКраїна УкраїнаДата створення 2003Керівне відомство Кабінет Міністрів УкраїниРічний бюджет 1 964 898 500 ₴[1]Голова Олег НаливайкоПідвідомчі ор...
Wife of the British Prime Minister The Right HonourableThe Countess of LiverpoolLady Louisa in 1793BornLouisa Theodosia Hervey(1767-02-00)February 1767Ickworth, Suffolk, EnglandDied12 June 1821(1821-06-12) (aged 54)London, EnglandKnown forSpouse of the prime minister of the United Kingdom (1812–1821)Spouse Robert Jenkinson, 2nd Earl of Liverpool (m. 1795)ParentsFrederick Hervey, 4th Earl of Bristol (father)Elizabeth Davers, Countess of Brist...
Daughter of U.S. president John Adams This article is about the daughter of U.S. president John Adams. For his wife (and this article's subject's mother), see Abigail Adams. Abigail Adams SmithBornAbigail Adams(1765-07-14)July 14, 1765Braintree, Province of Massachusetts Bay, British AmericaDiedAugust 15, 1813(1813-08-15) (aged 48)Quincy, Massachusetts, U.S.Burial placeHancock Cemetery in Quincy, MassachusettsSpouse William Stephens Smith (m. 1786)C...
G.H.A. Hansen, discoverer of M. leprae in 1873 The history of leprosy was traced to its origins by an international team of 22 geneticists using comparative genomics of the worldwide distribution of Mycobacterium leprae.[1] Monot et al. (2005) determined that leprosy originated in East Africa or the Near East and traveled with humans along their migration routes, including those of trade in goods and slaves. The four strains of M. leprae are based in specific geographi...
Ó RothláinRowlan, Rowland, Rowlands, Rollan, Rollin, Rolan and RowleyMap of Connacht, c. 10th centuryParent familyUí FiachrachPlace of originConnacht, IrelandTitlesChieftains of the Principality of CoolcarneyO'Rothlain reference on page 129 of The Irish AnnalsImage of page 114 from the book Irish Names and Surnames by Rev Patrick Woulfe (published 1922) Ó Rothláin (/oʊ ˈroʊlɔːn/ oh-ROH-lawn) is an Irish surname. The name is a Patronym meaning descendant of Rothlán. It is suggested ...
Swedish ice hockey clubAlmtuna ISCityUppsala, SwedenLeagueHockeyAllsvenskanFounded1932 (Hockey in 1947)Home arenaUpplands Bilforum ArenaColors General managerTony MårtenssonHead coachRobert KimbyWebsitealmtuna.com Almtuna IS is a Swedish ice hockey club based in Uppsala and is currently playing in HockeyAllsvenskan, the second highest league of ice hockey in Sweden. The team maintained its place in the Allsvenskan despite suffering relegation in the 2018–19 season f...
Type of autoantibody Immunofluorescence staining pattern of anti-centromere antibodies on HEp-20-10 cells Anti-centromere antibodies (ACAs; often styled solid, anticentromere) are autoantibodies specific to centromere and kinetochore function. They occur in some autoimmune diseases, frequently in limited systemic scleroderma (formerly called CREST syndrome), and occasionally in the diffuse form of scleroderma. They are rare in other rheumatic diseases and in healthy persons. Anti-centromere a...