Patterns2015
.pdfВозможныенедостатки
Схранителямогутбытьсвязанымиздержетные,еслихозядолженкопировать
большойобъеминформациидлязанесениявпамя |
тьхранилиеслиопетхлярациянения |
выполняедостаточночастося |
. |
81
6Команда.4 ( |
Command) |
|
Проблема |
|
|
Необходимопослобъектузапр,тьнезнаятом,выполнениескакойоперации |
|
|
запрошиктобудетполучателемно |
|
|
Решение |
|
|
ПаттернКоманда""разрыва |
етсвязьмеждуобъект,инициопеми, рацииующим |
|
объектом,имеющиминфортом,какеевыполнитьацию,кртогосоздаетсямеобъект |
|
|
"Команда",котможноррыйсширятьманимкакпулироватьобъектом. |
|
|
Этоп зводнимбъляотпректзапросынеизвемвлять |
стнымобъектамприложения, |
|
преобразсамзапрвобъектсвав |
|
. |
82
Связывакомандысобъектомие |
|
|
|
Вариантреализац,представленныйнаииаграмме,ос созданииованкоманды |
|
|
|
параметромобъекта |
-получателяобъект( |
–получательявляетсяпараметромконстр |
уктора |
конкреткома) ндыой |
|
|
|
Возможенвардинамическогоантсвязывкомполучателеман.Длядыияэтойцели |
|
|
|
командыдолженбытьспециальныйметод |
|
setReceiver(Receiver *) |
|
Диаграммаклассов
Обязанностиклассов
•Command - интерфейсдлявыполненоперац; ияи
• ConcreteCommand |
- опредсвязьмобъектомждуляет |
-получателемReceiverи |
действи;реализуетоп мрацию |
execute()путемвызовасоответствующихопераций |
|
|
83 |
|
объекта Receiver;
•Client - создаобъклассаеConcreteCommandкт иустанавливаегоп лучат; етля
•Invoker - обращаетсяккомандедлявыполнениязапроса;
•Receiver - располагаетинформациспособахвыполненоп йрацияй
Пример( class Command)
//Student - объект-получателъкоманды==
//управляемоеустройство
class Student;
// интерфейс команды class Command {
public:
virtual void execute () = 0;
};
Класс Student (получзаднавыполнениетельния)
class Student { |
|
protected: |
|
const char *state; |
const char *myName; |
Command *c; |
// похранениядлякоманды |
public:
void setState( const char *inState ) { state = inState; }
void printState() { cout << myName<<": "<<state << endl; } void saveCommand(Command *com) { c=com; }
// сохранениевыполняемойкоманды void doAction() { // метод,вызыизвнеамый
c->execute (); // выполняем команду
}
Student (const char * name){myName = name;}
};
Конкреткомандыые |
|
class CmdRun : public Command { |
// работает как invoker |
protected: |
|
Student *c; // объект,которымуправлятьдеткоманда |
|
public: |
|
CmdRun(Student * stud){ c=stud; stud->saveCommand(this); cout<<"CmdRun is ready\n";}
void execute () { c->setState("I am running along the river"); } // вызываетметод setState объекта-получат,.е.студенталя
};
class CmdShooting : public Command { protected:
Student *c; public:
84
CmdShooting(Student * stud){ c=stud; stud->saveCommand(this); cout<<"CmdShooting is ready\n";}
void execute () { |
c->setState("I am shooting on dartboard"); } |
}; |
|
Main
int main() {
Student* s[5] = { new Student("Petr"), new Student("Ivan"),
new Student("Leha"), new Student("Dasha"), new Student("Masha") }; cout<<"Students on the drill:\n\n";
//создаемкомандыуказаниемполучзапросадействиятеля:
CmdRun *cR1 = new CmdRun(s[0]); CmdShooting *cS1 = new CmdShooting(s[1]); CmdShooting *cS2 = new CmdShooting(s[2]);
CmdRun |
*cR2 = new CmdRun(s[3]); |
|
CmdShooting *cS3 = new CmdShooting(s[4]); |
||
// выполныем действие над объектом: |
||
for (int i=0; i<5; i ++) |
s[i]->doAction(); |
|
cout<<"\n Execute is done!\n\n"; |
||
// |
проверяем результат выполнения действия |
|
for (int i=0; i<5; i ++) |
s[i] -> printState(); |
|
return 0; |
|
|
}
Выполнение
85
Результатыприменпатткоманданиярна |
: |
1. Командаразрываетсвязьмеждуобъект,инициопеми, рациюующим |
объектом, |
имеющиминфортом,какеевыполнитьацию; |
|
2.команды - этосамыенастоящиеобъекты.Допускаетсяманимипулировать расширятьихточнотакже, вакслучаелюбымидругимиобъектами;
3. изпростыхкоможнособиратьандсостп( компоновщттернвные |
ик); |
4.добавлятьновыекоманды,посколькугконикакиесуществующиеклассыизменять ненужно.
6Посетитель.5 ( |
Visitor) |
|
|
Проблема |
|
|
|
Надкаждымобънекструктуоторойомнапример( ,де)выеваполняютсяоперации. |
|
|
|
Необхоопределновуюоперациюимо,нетьз |
меняяклассыобъектов |
. |
|
Решение |
|
|
|
Поместитьвзаимосвязанныеоперацииизкаждогоклассаотдельнбъект,называемый |
|
|
|
посетителем,передаватьего |
|
элементабстрклпоамеректногоссанеобходимости |
|
выпдополнительлненияопераций.Доп опервойныхение |
|
ациивыптольковняется |
|
посетителе. |
|
|
|
Класспримерчский - семантическоедеревокомпилятора.Существуютразличные программыиспользэтогдерева: ования
•Проверитьналичиеобъявленияпеременных
•Вывесписокпеременныхти
• Вычислобъемзанпамяимаемойть |
ти |
•Вывестидампприотладкепрограммы
86
Visitor объявляетоперацию |
visit()длякаждогокласElementвструктуре.Имяи |
сигнатураэтойоперациииденткласс,котфицируютпопосетителюыйзапрос |
|
visit()Врезульт.посетизн,элементатееткаель |
когоконкретногоклассапосещает. |
ConcreteVisitor - реализуетвсеоперации,объявленныеклассеVisitor.
Element - определяетоперацию |
accept(),котораяпринимаетпосетивкачествееля |
|
аргумента; |
|
|
ConcreteElement - реализуетоперацию |
accept(),прини |
мающуюпосетителякак |
аргумент
class Horse; class Tiger; class PussyCat; class Visitor { public:
Visitor() {}
virtual void visit(Horse *horse) {} virtual void visit(Tiger *tiger) {} virtual void visit(PussyCat *cat) {}
};
class HorseVisitor : public Visitor { public:
HorseVisitor() {}
87
void visit(Horse *horse) |
{ |
cout << "Horse dances waltz" << endl; } |
|
}; |
|
class TigerVisitor :public Visitor { |
|
public: |
|
TigerVisitor() {} |
|
void visit(Tiger *tiger) |
{ |
cout << "Tiger walks on his hind legs" << endl; }
};
class Animal { private:
int age; public:
Animal() {} virtual void feed()
{
cout << "Animal Feed" << endl;
}
virtual void accept(Visitor *v) {}
};
class Horse : public Animal { public:
Horse() {}
virtual void accept(Visitor *v) { v->visit(this); }
};
class PussyCat : public Animal{ public:
PussyCat() {}
virtual void feed() { cout << "PussyCat likes fish" << endl; }
};
class Tiger : public Animal{ public:
Tiger() {}
virtual void feed()
{
cout << "Tiger likes meet" << endl;
}
void growl() { cout << "Tiger growls" << endl; } virtual void accept(Visitor *v) { v->visit(this); }
};
int main(int argc, char *argv[]) {
Animal* zoo[4] = {new Tiger(),new Tiger(), new Horse(), new PussyCat()}; HorseVisitor *hVisitor = new HorseVisitor();
TigerVisitor *tVisitor = new TigerVisitor(); for (int i=0; i<4; i++){
88
zoo[i] -> feed();
zoo[i] -> accept(tVisitor); zoo[i] -> accept(hVisitor);
}
return 0;
}
Преимущества
•Упрдощаетсябавлнопвых,объниерацийродствдиняоперацииклассетнные "Посетитель".
• Позвлегкодобаляетнооперациивитьыеб змене |
ниясуществующегок дабъектов |
Недостатки
•ЗатрудненодобавновыхклассовениеКонкретныйЭлемент" ",посколькутребуется объявлениеновойабстрактноперацииклассеПосетитель" "й.
6.6 Перенаправление( |
Indirection) |
Проблема |
|
Какперераспределитьобязанн |
остиобъект,чтобыобеспечивтсутспрямоготьвие |
связывания? |
|
Решение |
|
Присвоитьгруппуобязанностейвысокойстепеньюзацепленияпромежуточномуклассу, котонепредставлконкретныйпонизпредметнойятияобластигосинтезировать(
89
искусственнуюсущнос тьдляобеспечениявысокогозацепленияслабогосвязывания).
6.7 Цепочкаобязанностей(Chain of Responsibility)
Проблема
Запрможетбытьсбрабнескольтанбъе. ктамиими
Решение
Связатьобъекты -получателизапросавце очкуередатьзапрвдольс этойцепочки, понекабудетобработан.КонкретныйОбр" "обрабатываетзапрос, которыйботчик отвечает,имеетдоск воемупреемникуупнапразапрсвопрляемус,еслитемнику неможетбрзасамботатьпрос.
Пример
90