Re[2]: Вопрос по паттерну Фабрика
От: Erop Россия  
Дата: 26.04.08 17:08
Оценка: 1 (1)
Здравствуйте, remark, Вы писали:

R>http://gzip.rsdn.ru/forum/message/1788774.1.aspx
Автор: remark
Дата: 17.03.06


IMHO, сложное очень решение
Вот смотри, один класс и в нём простой nested class template:
template< typename TInterface, typename TPtr = shared_ptr<TInterface> > class ObjectsFactory {
public:
    typedef std::string TypeId;
    typedef TPtr Ptr;

    static Ptr Create( const TypeId& id )
    {
        CreateFunction foo* = db()[id];
        assert( foo != 0 );
        return foo();
    }

    template<typename T> class Registrar {
    public:
        Registrar( const TypeId& id ) : id( id ) { reg( id, &creator ); }
        ~Registrar() { unreg( id ); }
    private:
        const TypeId id;
        Registrar( const Registrar& );
        void operator = ( const Registrar& );
        static Ptr creator() { return new T; }
    };
    
private:
    typedef Ptr CreateFunction();
    typedef std::map<TypeId, CreateFunction*> DB;
    static DB& db()
    {
        static DB creators;  // синглетон Маерса, так как Registrar -- статические объекты.
        return creators;
    }
    static void reg( const TypeId& id, CreateFunction* foo )
    {
        assert( foo != 0 && db()[id] == 0 );
        db()[id] = foo;
    }
    static void unreg( const TypeId& id )
    {
        assert( db()[id] != 0 );
        db()[id] = 0;
    }
};


Ну и теперь использование:
//  MyInterface.h
struct IMyInterface { virtual ~IMyInterface() {} };
typedef ObjectsFactory<IMyInterface> MyFactory;
const char* const MyInterfaceImpl1TypeId = "MySubsystem::MySubsubsystem::MyInterfaceImpl1";
const char* const MyInterfaceImpl2TypeId = "MySubsystem::MySubsubsystem::MyInterfaceImpl2";

//  MyInterfaceImpl1.h
class MyInterfaceImpl1 : public IMyImterface {
public:
    // тут реализация
};
// В MyInterfaceImpl1.cpp
static MyFactory::Registrar<MyInterfaceImpl1> impl( MyInterfaceImpl1TypeId );

//  MyInterfaceImpl2.h
class MyInterfaceImpl2 : public IMyImterface {
public:
    // тут реализация
};
// В MyInterfaceImpl2.cpp
static MyFactory::Registrar<MyInterfaceImpl2> impl( MyInterfaceImpl2TypeId );


IMHO радикально проще и прямее
И пользователям MyInterface, кстати, не надо знать о MyInterfaceImpl1.h, MyInterfaceImpl2.h и т. д...

Если таки хочется обязать пользователя иметь в классе-реализации статическое поле с TypeId, то можно приделать в ObjectFactory::Registrar() занчение параметра по умолчанию T::TypeId, например.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.