Программирование >>  Разработка устойчивых систем 

1 ... 153 154 155 [ 156 ] 157 158 159 ... 196


Из-за необходимости проверять флаг isFrog в функции greet() и во всех остальных функциях программа становится громоздкой, особенно если позднее потребуется добавить в систему дополнительные состояния. Делегирование операций объекту с переменным состоянием упрощает программу:

: C10:KissingPrincess2.cpp Паттерн Состояние. #include <1ostream> iinclude <string> using namespace std:

class Creature { class State { public:

virtual string responseO = 0:

class Frog : public State { public:

string responseO { return Ribbet! : }

class Prince : public State { public:

string responseO { return Darling! : }

State* state: public:

CreatureO : stateCnew FrogO) {} void greetО { cout state->response() endl:

void kissO { delete state: state = new PrinceO:

int mainO {

Creature creature:

creature.greetO:

creature.kissO:

creature.greetO: } III:-

Объявлять классы реализации вложенными или закрытыми не обязательно, но если это можно сделать, программа становится более стройной.

Обратите внимание: любые изменения в классах State автоматически распространяются в программе; вам уже не придется редактировать все классы, чтобы эти изменения вступили в силу.

Адаптер

Адаптер (Adapter) получает один тип и предоставляет интерфейс к другому типу. Предположим, вы пол5П1или две библиотеки или два фрагмента кода, которые используют одинаковые концепции, но выражают их по-разному (то есть обладают разным интерфейсом). Адаптация этих форм выражения друг к другу позволяет быстро придти к готовому решению.



Допустим, имеется класс, генерирующий числа Фибоначчи:

: C10:FibonacciGenerator.h #ifndef FIBONACCIGENERATOR H #define FIBONACCIGENERATORJ

class FibonacciGenerator {

int n;

int val[2]: public:

FibonacciGeneratorO : n(0) { val[0] = val[l] = 0: } int OperatorOO {

int result = n > 2 ? val[0] + val[l] : n > 0 ? 1 : 0:

++n:

val[0] = val[l]: val[l] = result: return result:

int count О { return n: }

#endif FIBONACCIGENERATOR H /:-

Как и всякий генератор, этот класс вызывается оператором ():

: СЮ:FibonacciGeneratorTest.срр #include <iostream> #include FibonacciGenerator.h using namespace std:

int mainO {

FibonacciGenerator f:

for(int i =0: i < 20: i++) cout f.countO : fO endl: } III:-

Требуется использовать этот генератор совместно с числовыми алгоритмами STL. К сожалению, алгоритмы STL работают только с итераторами; возникает несоответствие интерфейсов. Проблема решается Адаптером, который получает объект FibonacciGenerator и создает итератор, применяемый алгоритмами STL. Поскольку для работы числовых алгоритмов достаточно итератора ввода. Адаптер получается достаточно прямолинейным (во всяком случае, для программы, генерирующей итераторы STL):

: СЮ: Fibonacci Adapter, срр

Адаптация к существующему интерфейсу.

#include <iostream>

#1 nclude <numeric>

#i nclude Fi bonacci Generator.h

#include ../C06/PrintSequence.h

using namespace std:

class FibonacciAdapter { Получение итератора

FibonacciGenerator f:

int length: public:

Fibonacci Adapter(int size) : length(size) {} class iterator: friend class iterator: class iterator : public std::iterator< std::input iterator tag. FibonacciAdapter. ptrdiff t> {



FibonacciAdapters ар: public: typedef int value type: iterator(FibonacciAdapter& a) : ap(a) {} bool operator==(const iterators) const { return ap.f.countO == ap.length:

bool operator!=(const iterators x) const { return !(*this == x):

int operator*() const { return ap.fO: } iterators operator++() { return *this: } iterator operator++(int) { return *this: }

iterator beginO { return iterator(*this): } iterator endO { return iterator(*this): }

int mainO { const int SZ = 20: FibonacciAdapter al(SZ): cout accumulate:

accumulate(al.beginO. al.endO. 0) endl: Fibonacci Adapter a2(SZ). a3(SZ): cout inner product:

inner product(a2.begin(). a2.end(). aS.beginO. 0)

endl: FibonacciAdapter a4(SZ): int rl[SZ] = {0}:

int* end = partial sum(a4.begin(). a4.end(). rl): print(rl. end. partial sum . ): FibonacciAdapter a5(SZ): int r2[SZ] = {0}:

end = adjacent difference(a5.begin(). aS.endO. r2): print(r2. end. adjacent difference . ): } /:-

Чтобы инициализировать FibonacciAdapter, достаточно задать длину последовательности чисел Фибоначчи. При создании iterator мы сохраняем ссылку на вмещающий объект FibonacciAdapter для последующих обращений к FibonacciGenerator и length. Обратите внимание: при проверке равенства правостороннее значение игнорируется, поскольку существенно лишь то, достиг итератор конца последовательности или нет. Кроме того, operator++() не изменяет итератор; состояние FibonacciAdapter изменяется только одной операцией - вызовом функции operator() для FibonacciGenerator. Нам удается обойтись этой крайне упрощенной версией итератора, потому что для итераторов ввода устанавливаются крайне жесткие ограничения; в частности, каждое значение в последовательности может быть прочитано только один раз.

В функции main() Адаптер FibonacciAdapter используется для тестирования четырех числовых алгоритмов STL.

Шаблонный метод

прикладная библиотека позволяет создать новый класс, производный от одного или нескольких готовых классов. Новое приложение заново использует большую часть кода существующих классов, а переопределение одной или нескольких функ-



1 ... 153 154 155 [ 156 ] 157 158 159 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика