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

1 ... 155 156 157 [ 158 ] 159 160 161 ... 196


public:

virtual Answer canlHaveO = 0: virtual -GimmeStrategyO {}

class AskMom : public GimmeStrategy { public: Answer canlHaveO {

cout Mooom? Can I have this? endl

return NO:

class AskDad : public GimmeStrategy { public: Answer canlHaveO {

cout Dad. I really need this! endl:

return NO:

class AskGrandpa : public GimmeStrategy { public: Answer canlHaveO {

cout Grandpa, is it my birthday yet? endl:

return NO:

class AskGrandma : public GimmeStrategy { public: Answer canlHaveO {

cout Grandma. I really love you! endl:

return YES:

class Gimme : public GimmeStrategy {

vector<GimmeStrategy*> chain: public: GimmeO { chain.push back(new AskMomO): chain.push back(new AskDadO): chain.push back(new AskGrandpa()): chain.push back(new AskGrandmaO):

Answer canlHaveO ( vector<GimmeStrategy*>::iterator it = chain.begin() whileCit != chain.endO) if((*it++)->canIHaveO == YES) return YES: Bee попытки оказались безуспешными... cout Whiiiiinnne! endl: return NO:

-GimmeO { purge(chain): }

int mainO {



Фабрика

Если вы планируете добавлять в систему новые типы, разумнее всего воспользоваться поддержкой полиморфизма и создать общий интерфейс для новых типов. Таким образом, код систем отделяется от информации о конкретных типах, и добавление новых типов не нарушит работоспособности готового кода... на первый взгляд. Поначалу кажется, что изменения в программе ограничиваются объявлением нового производного типа, но это не совсем так. Объект нового типа все равно нужно создать, а в точке создания требуется задать используемый конструктор. Следовательно, если код создания объектов распределен по приложению, возникает та же проблема, что и при добавлении новых типов - вам придется искать в программе все точки, в которых учитывается конкретный тип объекта. В данном случае речь идет о создании типа, а не его использовании (которое обеспечивается автоматически средствами полиморфизма), но последствия остаются прежними: добавление нового типа порождает проблемы.

Одно из возможных решений - потребовать, чтобы все объекты создавались через единую Фабрику (Factory), вместо распределения кода создания объектов по системе. Если каждый раз, когда программе потребуется создать новый объект, она будет пользоваться услугами Фабрики, то для добавления нового типа объекта достаточно модифицировать Фабрику. Такая архитектура является разновидностью паттерна, часто называемого Фабричным методом (Factory method). Объекты создаются во всех объектно-ориентированных программах, а расширение программ с добавлением новых типов встречается достаточно часто, поэтому Фабрики могут стать одним из самых полезных паттернов проектирования.

В качестве примера рассмотрим классическую иерархию Shape. Один из способов реализации Фабрики основан на определении статической функции в базовом классе:

: C10:ShapeFactoryl.cpp linclude <iostream> linclude <stdexcept> linclude <cstddef> linclude <string> linclude <vector> linclude ../purge.h using namespace std;

class Shape {

Gimme chain; chain.canlHaveO; } /;-

Обратите внимание: контекстный класс Gimme и все классы Стратегий являются производными от общего базового класса GimmeStrategy.

Прочитав раздел с описанием Цепочки ответственности в книге БЧ, вы обнаружите, что его структура заметно отличается от приведенной ранее, потому что центральное место в нем занимает самостоятельная реализация связанного списка. Но если понять, что сущность Цепочки ответственности - перебор решений до обнаружения подходящего, становится ясно, что конкретная реализация механизма перебора в этом паттерне не важна.



public: virtual void drawO = 0: virtual void eraseO = 0: virtual -ShapeO {}

class BadShapeCreation : public logic error { public:

BadShapeCreation(string type)

: 1ogic error( Cannot create type + type) {}

static Shape* factoryCconst strings type) throwCBadShapeCreation):

class Circle : public Shape {

CircleO {} Закрытый конструктор

friend class Shape: public:

void drawO { cout Circle: :draw endl: } void eraseO { cout Circle: :erase endl: } -CircleO { cout Circle: :~Circle endl: }

class Square : public Shape {

SquareO {}

friend class Shape: public:

void drawO { cout Square:: draw endl: } void eraseO { cout Square::erase endl: } -SquareO { cout Square::-Square endl: }

Shape* Shape::factory(const strings type) throw(Shape::BadShapeCreation) { if(type == Circle ) return new Circle: if(type -= Square ) return new Square: throw BadShapeCreation(type):

char* si[] = { Circle . Square , Square . Circle . Circle . Circle , Square }:

int mainO { vector<Shape*> shapes: try {

for(size t i = 0: i < sizeof si / sizeof sl[0]: i++) shapes.push back(Shape::factory(si[i])): } catch(Shape::BadShapeCreation e) { cout e.whatО endl: purge(shapes): return EXITJAILURE:

for(size t i = 0: i < shapes.sizeO: i++) { shapes[i]->draw(): shapes[i]->eraseO:

purge(shapes): } III:-

Функция factoryO получает аргумент, по которому определяется тип создаваемого объекта Shape. В нашем примере аргумент относится к типу string, но он может



1 ... 155 156 157 [ 158 ] 159 160 161 ... 196

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