Под
• компоненты проверки достоверности;
• компоненты выделения лексем;
• компоненты грамматического разбора;
• компоненты синтаксического анализа;
• компоненты лексического анализа.
Эти части ПО можно объединить, чтобы сформировать уже знакомую нам программную конструкцию (листинг11.24).
// Листинг 11.24. Объявление класса language_processor
// и определение метода process_input
class language_processor {
//...
protected:
virtual bool getString(void) = 0;
virtual bool validateString(void) = 0;
virtual bool parseString(void) = 0;
//...
public:
bool process_input(void);
};
bool language_processor::process_input(void) {
getString();
validateString();
parseString();
//.. .
compareTokens();
//.. .
}
Во-первых, класс language_processor является абстрактным и базовым, поскольку он содержит чисто виртуальные функции:
virtual bool getString(void) = 0;
virtual bool validateString(void) = 0;
virtual bool parseString(void) = 0;
Это означает, что класс language_processor не предназначен для непосредственного использования. Он служит в качестве проекта для производных классов. Особенно стоит остановиться на методе process_input (). Этот метод представляет собой план работы, которую предстои т обобщит ь классу language_processor. Во многих отношениях именно это и отличает каркасные классы от классов других типов. Каркасный класс описывает не только обобщенную структуру и характер отношений между компонентами, но содержит и заранее определенные последовательности выполняемых действий. Однако в таком своеобразном описании поведения не указываются детали его реализации. В данном случае модель поведения задается набором чисто виртуальных функций. Каркасный класс не определяет, как именно эти действия должны быть выполнены, — важно то, что они должны быть выполнены, причем в определенном порядке. А производный класс должен обеспечить реализацию всех чисто виртуальных функций. При этом ответственность за корректность выполняемых действий целиком возлагается на производный класс. Каркасные классы по определению — договорные классы. Для достижения успешного результата требуется надлежащее выполнение обеих частей договора. Каркасный класс намечает четкий план, а производный реализует этот план в виде конкретного определения чисто виртуальных функций. Последовательность действий, «намеченная» методом process_input (), соблюдается в таких приложениях.
• Компиляторы
• Интерпретаторы ко
• Обработчики естественных языков
• Програ
• Упаковка-распаковка
• Протоколы пересылки файлов
• Графические интерфейсы пользователей
• Контроллеры устройств
Корректная разработка каркасного класса language_processsor (при надлежащем его тестировании и отладке) позволяет ускорить разработку широкого диапазона приложений.
Понятие каркасного класса также полезно использовать при разработке приложений, к которым предъявляются требования параллелизма. Так, использование агент-ных каркасов и каркасов «классной доски» фиксирует базовую структуру параллелизма и схемы работы в этих структурах. Майкл Вулдридж в своей книге [51] предлагает следующий обобщенный цикл управления агентами.
Алгоритм: цикл управления агентами