Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Объясните пожалуйста паттерн фабрика


Автор: Pro100MoNEy 3.7.2013, 22:43
Читаю С. Дьюхерста С++ Священные знания.
Там объясняется фабричный метод.
Вроде понятно обьект генерирует информацию о себе при этом мы не заботимся о том кто он конкретно.
Там приведен пример
Код
class Temp : public Employee {
   public:
      //...
      TempInfo *genInfo() const
         { return new TempInfo( *this ); }
      //...
};

Temp это служащий наследуемый от Employee при этом он может генерировать информацию о себе.
Код
class Employee {
   public:
      //...
      virtual HRInfo *genInfo() const = 0; // Фабричный метод
      //...
};

Код
Employee *e = getAnEmployee();
//...
HRInfo *info = e>genInfo();         // используется Фабричный метод

1)TempInfo должен быть наследником HRInfo?
2)Разве все равно не придется спросить тип служащего по какой-то внутренней информации, я имею ввиду не проще было бы ввести идентификатор(номер для типа служащего) чтобы просто определять кто он(рабочий, секретарь, водитель), хотя у разных рабочих разные поля, но тогда придется спросить о его типе как использовать объект о котором мало знаешь, чем это удобно?
3)Приведите пожалуйста пример фабрики другого плана может более наглядного, читаю теорию опыта пока мало но бездумно использовать патерны не хочу, объясните суть пожалуйста.

Автор: xvr 4.7.2013, 09:41
Цитата(Pro100MoNEy @  3.7.2013,  22:43 Найти цитируемый пост)
1)TempInfo должен быть наследником HRInfo?

Да

Цитата(Pro100MoNEy @  3.7.2013,  22:43 Найти цитируемый пост)
2)Разве все равно не придется спросить тип служащего по какой-то внутренней информации,

Ну собственно HRInfo это он и есть. В идеале при использовании полиморфизма нам вообще не надо знать конкретный тип служащего, любой наследник Employee должен сам знать о себе все, что надо. А мы должны знать только то, что доступно через базовый класс Employee 

Цитата(Pro100MoNEy @  3.7.2013,  22:43 Найти цитируемый пост)
3)Приведите пожалуйста пример фабрики другого плана может более наглядного, 

Например, вы делаете библиотеку для вычисления выражений, заданных в виде строки (пусть это будет встраиваемый куда то интерпретатор). И вы хотите дать возможность пользователю этой библиотеки добавлять в нее любые функции (по имени). Библиотека выдает из строки дерево разбора (AST). Вы заводите абстрактный узел для функции -
Код

class ASTNode {
...
public:
 virtual ASTValue evaluate() =0;
};

class ASTFunction : public ASTNode {
public:
 virtual void add_argument(ASTNode*) =0;
};

И делаете класс фабрики (с именем)
Код

class FunctionFabric {
 static FunctionFabric* root;
 FunctionFabric* next;
 const char* name;
public:
 FunctionFabric(const char* n) : name(n)
  {
   next=root;
   root=this;
  }
 virtual ASTFunction* create() =0;
 static ASTFunction* make(const char* nm)
   {
     for(FunctionFabric* f=root;f;f=f->next)
      if (strcmp(nm,f->name)==0) return f->create();
     return NULL;
   }
};
А что бы еще упростить жизнь пользователю вашей библиотеки делаете такой шаблонный класс и макрос:
Код

template<class Func>
class FuncReg : public FunctionFabric {
public:
 FuncReg(const char* n) : FunctionFabric(n) {}
 ASTFunction* create() {return new Func;}
}; 
#define FUNCREG(nm) static FuncReg<FUNC_##nm> local_static_registrar_##nm(#nm)
После этого добавление новой функции пользователем выглядит элементарно (например добавим 'sin'):
Код

class FUNC_sin : public ASTFunction {
...
};
FUNCREG(sin);
Ну и создание функции в библиотеке
Код

ASTFunction* func = FunctionFabric::make("sin");



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)