Паттерн Фабрика (Factory)

      Комментарии к записи Паттерн Фабрика (Factory) отключены

Помечено: , , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 4 мес., 3 нед. назад.

  • Автор
    Сообщения
  • #3616

    Фабрика, по сути, это виртуальный конструктор. Предположим, у нас есть базовый класс и несколько его наследников. Мы хотим создавать объекты наследников, скрывая их за указателем на базовый класс. Кроме того, мы хотим, чтобы тип наследника определялся в динамике через какой-то параметр. Например, через строковое имя класса, как это сделано в моем примере.

    #include <iostream>
    #include <string>
    #include <map>
    #include <boost/shared_ptr.hpp>
    
    template <class base>
    class factory
    {
    public:
    
        typedef boost::shared_ptr<base> base_ptr;
    
        template <class derived>
        void reg(std::string const& name)
        {
            factories[name] = base_type_ptr(new derived_type<derived>);
        }
    
        base_ptr create(std::string const& name)
        {
            return factories[name]->create();
        }
    
    private:
    
        class base_type
        {
        public:
    
            virtual ~base_type() {}
    
            virtual base_ptr create() const = 0;
        };
    
        typedef boost::shared_ptr<base_type> base_type_ptr;
    
        template <class T>
        class derived_type : public base_type
        {
        public:
    
            virtual base_ptr create() const
            {
                return base_ptr(new T);
            }
        };
    
        typedef std::map<std::string, base_type_ptr> factory_container;
    
        factory_container factories;
    };
    
    class furniture
    {
    public:
    
        virtual ~furniture() {}
    
        virtual void show() = 0;
    };
    
    class table : public furniture
    {
    public:
    
        virtual void show()
        {
            std::cout << "The big black wooden table" << std::endl;
        }
    };
    
    class chair : public furniture
    {
    public:
    
        virtual void show()
        {
            std::cout << "The old rocking chair" << std::endl;
        }
    };
    
    int main()
    {
        typedef factory<furniture> furniture_factory;
        typedef furniture_factory::base_ptr furniture_ptr;
    
        furniture_factory fct;
    
        fct.reg<table>("Table");
        fct.reg<chair>("Chair");
    
        furniture_ptr f1 = fct.create("Table");
        furniture_ptr f2 = fct.create("Chair");
    
        f1->show();
        f2->show();
    
        return 0;
    }

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

    В большинстве случаев программисты используют фабрики там, где они на самом деле не нужны. Зачастую использование фабрик говорит о переусложненной типизации системы.

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

Для ответа в этой теме необходимо авторизоваться.