Russian Qt Forum
Ноябрь 23, 2024, 08:03 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Объясните пожалуйста паттерн фабрика  (Прочитано 6677 раз)
FakeMoNEy
Гость
« : Июль 03, 2013, 22:38 »

Читаю С. Дьюхерста С++ Священные знания.
Там объясняется фабричный метод.
Вроде понятно обьект генерирует информацию о себе при этом мы не заботимся о том кто он конкретно.
Там приведен пример
Код:
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)Приведите пожалуйста пример фабрики другого плана может более наглядного, читаю теорию опыта пока мало но бездумно использовать патерны не хочу, объясните суть пожалуйста.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Июль 03, 2013, 22:45 »

Там приведен пример
Там ошибка в примере. Вы правильно его поняли/процитировали?

Фабрика это функция/метод, который может порождать другие объекты.
Простой пример, нужно генерировать разные объекты в зависимости от ключа (не буду мудрить, пусть будет switch):
Код
C++ (Qt)
class Base;
class Obj1 : public Base {};
class Obj2 : public Base {};
class Obj3 : public Base {};
 
class Factory
{
public:
   Base *build( int id ) const
   {
       switch( id )
       {
       case 1:    return new Obj1();
       case 2:    return new Obj2();
       case 3:    return new Obj3();
       }
       return nullptr;
   }
};
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Июль 04, 2013, 16:17 »

Напр есть 3 загрузчика имеджей
Код
C++ (Qt)
class CLoaderPNG;
class CLoaderJPG;
class CLoaderBMP;
 
И дан файл (полное имя) fileName. При этом однако расширения в имени может и не быть, а на nix системах тип файла должен использоваться вперед расширения. Попробуйте загрузить файл прямолинейно, "без всяких фабрик" просто перебирая загрузчики - их ведь всего 3. Возмжно начав набрасывать схему/псевдокод Вы обнаружите что почему-то получается ужасно коряво  Улыбающийся
Записан
Bepec
Гость
« Ответ #3 : Июль 04, 2013, 21:43 »

Я п по сигнатурам определял Веселый
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июль 05, 2013, 13:26 »

Я п по сигнатурам определял Веселый
Да, это кажется "совсем просто", но начните писать - и попрет из всех щелей  Улыбающийся
Записан
Bepec
Гость
« Ответ #5 : Июль 05, 2013, 14:40 »

У меня до сих пор работает разборщик файлов по сигнатурам Улыбающийся Там всё просто, стандарты файлов все описаны.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июль 05, 2013, 15:22 »

У меня до сих пор работает разборщик файлов по сигнатурам Улыбающийся Там всё просто, стандарты файлов все описаны.
Без кода (пусть псевдо) мы просто засоряем эфир
Записан
Bepec
Гость
« Ответ #7 : Июль 05, 2013, 15:38 »

Igors вы в курсе сигнатур файлов?
"GIF89" "PNG" "MZђ". Необходимо только прочитать спецификацию файла.

Псевдокод поиска в файле в определённом месте строки? неужели indefOf нуждается в псевдокоде Улыбающийся Нет ничего сложного. Правда для нескольких десятков специфичных форматов нужен анализ. Но сигнатуры обычно или в начале, или в первой сотне символов.

Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #8 : Июль 05, 2013, 19:11 »

Без кода (пусть псевдо) мы просто засоряем эфир

https://qt.gitorious.org/qt/qtbase/blobs/stable/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #9 : Июль 05, 2013, 19:56 »

3)Приведите пожалуйста пример фабрики другого плана может более наглядного, читаю теорию опыта пока мало но бездумно использовать патерны не хочу, объясните суть пожалуйста.

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


Задача Фабрики - создание объекта таким образом, что бы скрыть от пользователя правила, по которым создаются объекты.


Вот например: есть задача: нужно создать объект, указав символьное имя его класса.
Как это сделать? А хочется достаточно гибкую и расширяемый механизм. Что бы не городить многочисленные свитчи.

Вот здесь и приходит на помощь фабрика, в которую можно заложить достаточно замысловатые правила, по которым создаются объекты:

Код:
#include <iostream>
#include <string>
#include <map>
using namespace std;

struct Foo{ virtual ~Foo(){}; };
struct Bar0 : Foo {};
struct Bar1 : Foo {};

class Factory
{
  struct Base{ virtual Foo * build()const=0; };

  template<class T> struct Builder : Base{ Foo * build()const { return new T; }; };

   static std::map<std::string, Base*>& GetMap()
   {
      static std::map<std::string, Base*>keys;
      return keys;
   }
public:

  template <class T>  static void reg(const std::string& key)
  {
    cout<< "register: "<<key<<endl;
    GetMap()[key]= new Builder<T>();
  }

  static Foo* build(const std::string& key)  {    return GetMap()[key]->build();  }
};

#define REGISER(class_name) Factory::reg<class_name>(#class_name);

int main()
{
   REGISER(Bar0);
   REGISER(Bar1);

   cout << typeid( *Factory::build("Bar0")).name()<<endl;
   cout << typeid( *Factory::build("Bar1")).name()<<endl;
  
  
}

Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.147 секунд. Запросов: 22.