Patterns2015
.pdf6.1 Состояние |
|
|
Проблема |
|
|
Вкодепоявляетнеобходимосоченьятавитьразветвленныйь |
if,состоящизмногихй |
|
ветвей.Ввыбор |
зависитотсостоянияобъекта.Однажеструктура |
if появляется |
несколькихточкахпрограммы.Фактическинеобходимоварьповедениерообъектаать |
|
|
зависимостиотвнутреннегосостояния. |
|
|
Решение |
|
|
Поместитькаждуюветвьотдельныйкласс |
|
. Фактическиповедениеобъектаописывается |
некоторымконечнымавто |
атом.Назовемклассэтогоконтекстом. |
|
Состояние
1) |
Класс State опредеинтерфейсинкапляетповеден,ассоуляциис я рованного |
|
|
||
|
конкретнымсостояниемобъекта |
|
Context |
|
|
2) |
Класс Context |
хранитэкз |
емплярподкласса |
State,соответствующий |
текущему |
|
состоянию |
|
|
|
|
3) |
Впроцессеработыобъклассакт |
|
Context делегируетзависящиеотсостояниязапросы |
|
|
|
текущобъектуму |
ConcrState_xxx () |
|
|
71
|
4) ConcrState_xxx ()реализуетповедение,соо состояниюветствующее |
<xxx> объекта |
|
|
Context |
|
|
Пример |
|
|
|
|
Студентбакалавриатапробученияцеимеслсехарактеристикидующие |
: |
|
• Зачинакурс1 (ленотояние |
B – студентбакалавриата) |
|
|
• Сдалобесессииперевнаследкурсенющий |
|
||
• |
Учитсянакурсе |
i, 1<=i<=4послеусп(четырехшныхсдачвсо |
стоянии B двухсессий |
|
переходитвсостояние |
A) |
|
• |
УспешнозащитилВКР |
– выпускнуюквалификационнуюработу |
(состояние A)ирешил |
|
ещепоучитьсяперешел( всостояние |
B) |
|
КодState
#ifndef __STATE #define __STATE class State { public:
virtual void execute( Context *inCon ) = 0;
};
#endif
КодStateA
class StateA : public State { public:
virtual void execute(Context *inCon);
};
void StateA::execute(Context *inCon) {
cout << "AAA: I have got bachelor diploma!!! \n"; inCon->setState( new StateB() );
}
КодStateB |
|
class StateB : |
public State { |
private: |
|
int count; |
|
public: |
|
virtual void execute(Context *inCon); StateB();
};
void StateB::execute(Context *inCon) { cout << "BBB: I am a stuent\n";; count++;
if( count == 4 ) {
inCon->setState( new StateA() );
72
}
}
StateB::StateB() { count = 0;
}
КодContext.h
#ifndef CONTEXT_H #define CONTEXT_H class Context { private:
State *currentState; public:
void setState( State *inSt ); void execute();
Context();
};
#endif
КодContext.cpp
#include "context.h”
void Context::setState( State *inSt ) {
if( currentState ) delete currentState; currentState = inSt;
}
void Context::execute() {
if( currentState ) currentState->execute(this);
}
Context::Context() { currentState = new StateB();
}
Кодmain
#include "include.h" int main()
{
Context t;
t.setState( new StateB() ); for( int i = 0; i < 23; i++ ) {
t.execute();
}
return 0;
}
Примервыполне ния
73
Windows Workflow Foundation |
|
|
|
MicrosoftвнедрилоснованноенасостоянияхпроектированиеVisualПри Studio. |
|
|
|
созданиитакоговидапрпредлагаетсяектазадатьконечный |
автомат,определитьпереходы |
|
|
вдругиевзависимостиотусловийнаписатькодлог |
ики работы длякаждогосостояния |
. |
|
Пример:Оплатазауслугисотовыхопербанкоматеторовдиаграмма( Workflow) |
: |
|
|
|
|
|
|
|
|
|
|
74
В вышеприведенныхработах |
используеподхкогда, переключаетосякодниев |
|
1, приэтом |
состоянии.Можноиспользовать |
дход, разрабавторатанный |
мивмонографии |
|
переключениесостоянийпроизлогикиводитсяуправлкомпонентающего |
|
|
всоответствии |
сзаданнымипереходами,вероятнусл вистями |
: |
|
|
6Наблюдатель.2 ( |
Observer) |
|
|
|
Проблема |
|
|
|
|
Врезультаразбиесиснамтениямыожествосовмест |
|
ноработклассовющих |
||
появляетсянеобходимостьподдержисогласовасостояниеезаимать связанных |
|
|
||
объектов.Нонехотелбы,чтзасогласованностьбысьнадобыплжесатиоткойь |
|
|
|
|
связанностьюклассов,таккакэтоуменьшаетвозмповторногожностиисполь |
|
|
зования. |
|
Необходимоустанотакуюзавтипаситьодин«комность»междуогимобъектами, |
|
|
|
|
чтобы приизменениисостоянияодногообъектавсезависящиеотнегообъекты |
|
|
|
|
оповещаются ипринеобходимавтоматическиобн. стивляются |
|
|
||
Решение |
|
|
|
|
Ключевклассые |
– субъект( |
Subject)инаблюдатель( |
Observer). Observer должензнать |
|
обизменениисостоянийобъекта |
|
Subject.Приэтомнеобхоподдерживатьнизкиймо |
|
|
уровеньсвязывания |
Subject с Observer. |
|
|
|
Рассмотримпростойвариант: |
|
закаждымобъектомможетнаблюдатьнескол |
|
ко |
наблюдателей,ноодинслетолькозоднимаитобъектомель |
|
|
|
|
1 Старолетов.М.Крючкова, Е.Н.Моделированиеспределённыхмногокпрограммныхмпонесистем тных |
|
|
|
|
ихтестированиенаосноавтоматныхвероятнмоделей.Монографиястных. |
|
— Барнаул: |
Изд-воАлтГТУ, |
|
2011. — 107с. — ISBN 978-5-7568-0859-9 |
|
|
75
76
Объекты-наблюдателидинамиче |
скирегистрируютсядляполучения |
информации |
|
нексобторомв(ытииполненадпискасобытия). |
|
Затемпреализацииусловленного |
|
событияоповещаются |
всеобъекты |
- подписчики. |
|
Взависимостиотреализациинаблюдателимогутполучитьнфоробизмененияхацию |
|
||
либочерезпараметрфункции |
|
notify(), либоспомощьювызовафункции |
getState() у |
наблюдаемобъекта.Этоозн,чтонаблюдательчаетгознает,от |
|
копгонсообщениелучил |
|
(узналвмоментподпилузналивмоментскивыполнения |
|
notify()). |
Пример1
Задача: Естьавтомобиль,которыйдвижетконтроляпотрасСистема. следитзих передвижением.
Первыйва еализациинт |
– наблюдательполучаетинф |
ормациюобизмененияхчерез |
параметрфункции |
update(x) |
|
Observer - Gai
class Observer { public:
virtual void update(int x) = 0; // данные через x в update(x)
};
class GAI: public Observer { private :
int oldState, curState;
void check(){ if ( oldState < curState ) <обработка 1> else <обработка 2>
}
public:
77
void update(int x){ oldState = curState; curState = x; if ( oldState >= 0 ) check();
}
GAI(){curState = -1;} };
Subject
class Subject{ protected:
Observer * myObserver; public:
void attach(Observer *a) {myObserver =a;}
void dettach (Observer *a) {if (a == myObserver ) myObserver = NULL; } virtual void notify() = 0;
Subject(){}
~Subject(){}
};
Jeep
class Jeep : public Subject { private:
int x; public:
Jeep(int start) { x=start; } ~Jeep(){}
void notify() { myObserver -> update(x); }
//данныечерезпараметр |
x в update(x) |
int getState() { return x; } |
|
void setState(int newX){ x = newX; |
notify(); } |
}; |
|
Main |
|
#include "subject.h" |
|
#include "observer.h" |
|
#include "gai.h" |
|
#include "jeep.h" |
|
using namespace std; |
|
int main(){ |
|
Observer * gai= new GAI(); |
|
Jeep * a777ab = new Jeep(100); |
|
a777ab -> attach(gai); |
|
for (int i=0; i< 10; i++) { |
|
if (i%3) a777ab -> setState ( a777ab -> getState() + i*10 ); else a777ab -> setState ( a777ab -> getState() - i*8 );
}
return 0;
}
Результатработы
78
Пример2
Задачанеизменяется: Естьавтомобиль,которыйдвижетконтроляпотрасСистема. следитзаихпередвижением.
Втоваройеализациинт |
|
– наблюдательполучаетинфоробизмсененияхацию |
|
помощьювызовафункции |
getState() унаблюдаемогообъекта.Тогднаблюдательдолжен |
|
|
знатьнаблюобъект,чтодоаестигавмыйомподпискиенасообщениятсянтвызовом |
|
|
|
attach() функциирегистрациинаблюдобъектап раметромемого |
this ,котораяз |
апомнит |
|
этотнаблюдаемыйобъект. |
|
|
|
Observer
class Observer { protected:
class Subject * mySubjects;
// наблюдаемый объект
public:
virtual void update(int x) = 0;
void setSubject(Subject * s){mySubjects = s;} // получить наблюдаемый объект
};
Jeep
class Jeep : public Subject { private:
int x;
public:
int getState(){return x;} //функция,котораявызываетсяизнаблюдателя
Jeep(int start){x=start;}
79
void notify(){myObserver -> update(x); } void attach(Observer *a) { Subject::attach(a);
a->setSubject(this);} void setState(int newX){x=newX;
myObserver->update(x);}
};
Gaiиmain
void Gai::update(){
int x = mySubjects->getState(); oldState = curState;
curState = x;
if ( oldState >= 0 ) check();
}
Код main остаетсябези менения!
Пример3
ЕстудентыьСидоров,ИвановПетров,закоторыминаблюдаютродконкретные( тели укаждогосту дента)идеканато( винлястехудент),аснекоторыхпзастудентомв Петровым пристальнаблюдаетвое. комат
Реализация - у |
каждогоконкретного |
Subject |
иконкретного Observer естьписки |
наблюдателейи соответственно.Далеереализацимых |
|
якаквпри1мерели2. |
|
Преимущества прииспользованииНаблюдателя |
|
|
|
• Наблюдатисубъектыничнезнаютдругголидруге |
|
|
– этоотличныйпримерслабого |
зацепления |
|
|
|
• Появлениеновыхтиповнаблюдатнетребусуществующегоизм лнениякодай |
|
|
|
субъек.Достаточов |
нопростозарегистрироватьновогонаблюдателя |
|
• Измененвалгорработысубъектовиятмин блюхневлияютддруганаателей
6Хранитель.3 ( Memento)
Проблема
Необходимозафиксировповеобъектареениелямехлизтьотката.нцизмаи
Решение
Зафиксироватьивынестизапределыобъектаеговнутреннеесостояниетак,чтобыможно быловосстановитьобъект.
80