Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Patterns2015

.pdf
Скачиваний:
10
Добавлен:
14.02.2015
Размер:
42.45 Mб
Скачать

6.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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]