Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 11:25
Оценка: 31 (8) +1
Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.
Может кому будет полезно. Или кто выскажет конструктивные замечания.


// Некий интерфейс, реализации которого будем создавать с помощью фабрики
struct IHeader
{
    typedef boost::shared_ptr<IHeader> Ptr;
    virtual ~IHeader() = 0 {};
};

// Интерфейс метакласса реализации IHeader
struct IHeaderWrapper
{
    typedef boost::shared_ptr<IHeaderWrapper> Ptr;
    virtual ~IHeaderWrapper() = 0 {};

    virtual IHeader::Ptr create() = 0;
};

// Фабрика реализаций IHeader
class HeaderFactory
{
private:
    typedef std::map<int, IHeaderWrapper::Ptr> map;

    static map& wrappers()
    {
        static map wrappers_instance;
        return wrappers_instance;
    }

public:
    // Метод создания экземпляра
    static IHeader::Ptr create(int type)
    {
        map::iterator iter = wrappers().find(type);
        if (wrappers().end() != iter)
            return iter->second->create();
        else
            throw std::runtime_error("unknown header type");
    }

    // Метод добавления нового типа экземпляра
    static void add(int type, IHeaderWrapper::Ptr wrapper)
    {
        if (!wrappers().insert(std::make_pair(type, wrapper)).second)
            throw std::logic_error("Header type added twice");
    }
};

// Метакласс реализации IHeader
template<typename HeaderType>
struct HeaderWrapper : IHeaderWrapper
{
    virtual IHeader::Ptr create()
    {
        return IHeader::Ptr(new HeaderType);
    }
};

// Базовый класс для реализаций IHeader - обеспечивает саморегистрацию реализаций в фабрике
template<typename Derived>
struct Header : IHeader
{
private:
    struct Initializer
    {
        Initializer()
        {
            // Саморегистрация
            HeaderFactory::add(Derived::TYPE, IHeaderWrapper::Ptr(new HeaderWrapper<Derived>));
        }
    };

    static Initializer initializer;

protected:
    ~Header()
    {
        // Надо обязательно заюзать эту переменную
        (void)initializer;
    }
};

template<typename HeaderType> typename Header<HeaderType>::Initializer Header<HeaderType>::initializer;

// Реализация IHeader
struct Header1 : Header<Header1>
{
    static const int TYPE = 1;
    // Реализация
};

// Реализация IHeader
struct Header2 : Header<Header2>
{
    static const int TYPE = 2;
    // Реализация
};

// Реализация IHeader
struct Header3 : Header<Header3>
{
    static const int TYPE = 3;
    // Реализация
};


int main()
{
    IHeader::Ptr h1 = HeaderFactory::create(1);
    IHeader::Ptr h2 = HeaderFactory::create(2);
    IHeader::Ptr h3 = HeaderFactory::create(3);
    IHeader::Ptr h4 = HeaderFactory::create(4); // Тут будет исключение
}




В принципе тут можно уменьшить кол-во классов путём совмещения: например код из HeaderFactory можно поместить в IHeader. Тут так сказать всё разложено по полочкам.

Заполнение фабрики информацией о реализациях происходит во время инициализации глобальных объектов. Т.е. уже к main() она "константная".

Сразу предвижу замечания по поводу оверхеда. Возможно он есть тут. Конечно для тривиальных случаев делать так не стоит. Но для сложных, я считаю такое решение оправдано. Зато это создаёт некую инфраструктуру, с которой "пользовательские классы" становяться проще. Зато тут всё ортогонально и все классы и методы простые, короткие и понятные. А с "более простыми решения" рука об руку идут switch'и, дублирование и другие прелести.

Плюс эту инфрастуктуру можно нагрузить ещё всякими дополнительными бонусами.

1. Например, в фабрику можно поместить метод:

// Фабрика реализаций IHeader
class HeaderFactory
{
public:
    // Проверка на существование типа
    static bool exists(int type)
    {
        return wrappers().end() != wrappers().find(type)
    }
};


Например, загрузили из БД тип (число), сразу можно проверить, а правилное ли это число, есть ли у нас такой тип.

2. С каждой реализацией можно связать гораздо больше информации, чем просто тип

// Реализация IHeader
struct Header1 : Header<Header1>
{
    // Связываем с типом числовое значение
    static const int TYPE = 1;

    // Связываем с типом другой тип. Например, тип диалога, который может отобразить информацию о данной реализации
    typedef Header1Dlg DlgType;

    // Связываем с типом некий флаг
    static const bool IS_SIMPLE = true;

    // Связываем с типом строку, которую мы можем выводить пользователю
    static const char* GetName()
    {
        return "SOME_HEADER";
    }

    // Реализация
};


Соответственно надо расширить IHeaderWrapper для поддержки этих значений.

3. В фабрику можно добавить метод для получения всех типов:

// Фабрика реализаций IHeader
class HeaderFactory
{
public:
    // Получить список всех метаклассов
    static std::vector<IHeaderWrapper::Ptr> getAllWrappers();
};



Имея всё это можно написать функцию, например, для заполнения комбобокса информацией о всех существующих типах + с каждым элементом комбобокса связать код этого типа.

Или функцию, которая выберет из всех типов типы, которые отвечают заданному критерию, например, у которых флаг IS_SIMPLE == true;

В общем можно много чего ещё полезного реализовать, причём реализовать так сказать "красиво".


Плюсы:
1. Практически нулевое дублирование, что важно для сопровождаемого кода
2. Инрастуктура функциональная, расширяемая и "умная"
3. Сами классы реализаций интерфейсов абсолютно самодостаточные, самоописываемые, т.е. высокая локальность данных и функций
4. Чтобы добавить новый класс реализации надо просто его описать и его поддержка автоматически появиться везде где она должна быть. Чем не может похвастаться традиционный подход — саму реализацию добавил, добавил её поддержку в фабрику, добавил её поддержку в интерфейс пользователя, а при загрузке из БД забыл.


... что-то уже до целой статьи дотягивает


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Саморегистрация классов в фабрике
От: Аноним  
Дата: 17.03.06 11:37
Оценка:
Здравствуйте, remark, Вы писали:

R>Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.

R>Может кому будет полезно. Или кто выскажет конструктивные замечания.

См. Александреску "Современное проектирование...". ИМХО там реализация лучше. А в последних версиях Loki аффтар "творчески переработал" этот кусок.
Re: Саморегистрация классов в фабрике
От: DigitalGuru Россия http://svetlyak.ru
Дата: 17.03.06 11:37
Оценка: +2 :))
Здравствуйте, remark, Вы писали:

R>Может кому будет полезно. Или кто выскажет конструктивные замечания.


Так и хочется написать: "Ниасилил, слишком многа классав"
Re[2]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 12:13
Оценка:
Здравствуйте, DigitalGuru, Вы писали:

DG>Здравствуйте, remark, Вы писали:


R>>Может кому будет полезно. Или кто выскажет конструктивные замечания.


DG>Так и хочется написать: "Ниасилил, слишком многа классав"


Надеюсь хоть кто-то дочитает до конца

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Саморегистрация классов в фабрике
От: _nn_  
Дата: 17.03.06 12:30
Оценка: :)
Здравствуйте, remark, Вы писали:

R>Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.

R>Может кому будет полезно. Или кто выскажет конструктивные замечания.


R>
// <skip>

R>[ccode]
R>// Реализация IHeader
R>struct Header1 : Header<Header1>
R>{
R>    // Связываем с типом числовое значение
R>    static const int TYPE = 1;

R>    // Связываем с типом другой тип. Например, тип диалога, который может отобразить информацию о данной реализации
R>    typedef Header1Dlg DlgType;

R>    // Связываем с типом некий флаг
R>    static const bool IS_SIMPLE = true;

R>    // Связываем с типом строку, которую мы можем выводить пользователю
R>    static const char* GetName()
R>    {
R>        return "SOME_HEADER";
R>    }

R>    // Реализация
R>};
R>


Можно передавать через шаблон некоторые аргументы:
Бонус небольшой изврат :-D
struct Header1 : Header<Header1,
                        1,
                        Header1Dlg,
                        true,
                        mpl::list<mpl::long_<'SOME'>, mpl::long_<'_HEA'>, mpl::long_<'DER'> > >
{
};


R>Плюсы:

R>1. Практически нулевое дублирование, что важно для сопровождаемого кода
Что насчет автоинкремента номера ?
Что-то вроде:
template<typename T>
struct Header
{
 static const ID = increment_meta_function<T>::value;
};

R>2. Инрастуктура функциональная, расширяемая и "умная"
Пока не будут применятся в полную метапрограммирование на шаблонах и на макросах не будет полностью расширяемая
R>3. Сами классы реализаций интерфейсов абсолютно самодостаточные, самоописываемые, т.е. высокая локальность данных и функций
R>4. Чтобы добавить новый класс реализации надо просто его описать и его поддержка автоматически появиться везде где она должна быть. Чем не может похвастаться традиционный подход — саму реализацию добавил, добавил её поддержку в фабрику, добавил её поддержку в интерфейс пользователя, а при загрузке из БД забыл.


R>... что-то уже до целой статьи дотягивает

Приветствуется

R>
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Саморегистрация классов в фабрике
От: rg45 СССР  
Дата: 17.03.06 12:51
Оценка: -1
"remark" <38267@users.rsdn.ru> wrote in message news:1788774@news.rsdn.ru...
> Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.
> Может кому будет полезно. Или кто выскажет конструктивные замечания.
>...

А что, мне нравится.
Конечно слабым местом является то, что идентификаторы нужно назначать в каждом типе руками и, похоже, применительно к тому примеру, от которого родился этот топик, от этого никуда не денешься: в потоке данных хранятся именно числа. А вот в общем случае, ключ мапа можно было бы сделать строковым и загонять туда typeid(Derived).name(), вот это вообще будет хорошее решение.
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Саморегистрация классов в фабрике
От: night beast СССР  
Дата: 17.03.06 13:15
Оценка:
Здравствуйте, rg45, Вы писали:


R>"remark" <38267@users.rsdn.ru> wrote in message news:1788774@news.rsdn.ru...

>> Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.
>> Может кому будет полезно. Или кто выскажет конструктивные замечания.
>>...

R>А что, мне нравится.

R>Конечно слабым местом является то, что идентификаторы нужно назначать в каждом типе руками и, похоже, применительно к тому примеру, от которого родился этот топик, от этого никуда не денешься: в потоке данных хранятся именно числа. А вот в общем случае, ключ мапа можно было бы сделать строковым и загонять туда typeid(Derived).name(), вот это вообще будет хорошее решение.

лучше & typeid(Derived).
или
static const char * id () { staric const char name[]="name"; return name; }
Re[3]: Саморегистрация классов в фабрике
От: rg45 СССР  
Дата: 17.03.06 13:31
Оценка:
"night beast" <48023@users.rsdn.ru> wrote in message news:1789093@news.rsdn.ru...

> лучше & typeid(Derived).

> или
>
> static const char * id () { staric const char name[]="name"; return name; }
>


Да, но это уже зависит от конкретных условий приложения. Если в приложении подгружаются dll-модули, то выражение & typeid(Derived) , скрее всего, будет иметь разное значение в разных модулях. И если задача стоит о сохранении абстрактных данных в поток(файл) с последующей загрузкой этих данных, возможно даже другим приложением, то тоже не пройдет такой подход. Со строкой, конечно же, медленнее, но зато круг решаемых задач шире.
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re: Саморегистрация классов в фабрике
От: Аноним  
Дата: 17.03.06 13:33
Оценка:
Так это, с чего всё начиналось —
да, switch'а нет, зато есть std::map, что в плане производительности ещё хуже
Re[3]: Саморегистрация классов в фабрике
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 17.03.06 14:06
Оценка:
Здравствуйте, remark, Вы писали:

R>Надеюсь хоть кто-то дочитает до конца


Дочитал... Полезное решение..

Вот только есть одна проблема, о которой стоит, наверно, вспомнить...
При реализации классов в статической библиотеке существует вероятность, что они будут таки проигнорированы линкером....
Re[2]: Саморегистрация классов в фабрике
От: Oval  
Дата: 17.03.06 16:59
Оценка:
Идея авторегестрации — ссылка на конструктор статического объекта в деструкторе?
Как это объясняет стандарт?


R>"remark" А вот в общем случае, ключ мапа можно было бы сделать строковым и загонять туда typeid(Derived).name(), вот это вообще будет хорошее решение.

hash(typeid(Derived).name())
будет хорошим решением (реализацию hash для string взять из java)
Re[2]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 17:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, remark, Вы писали:


R>>Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.

R>>Может кому будет полезно. Или кто выскажет конструктивные замечания.

А>См. Александреску "Современное проектирование...". ИМХО там реализация лучше. А в последних версиях Loki аффтар "творчески переработал" этот кусок.



Нет, там другое.
Часть функциональности, о которой я говорю там есть. Но только часть, причём не главная. Там нет саморегистрации. Там нет возможности нагружать эту инфроструктуру дополнительной функциоанльностью. То о чём я говорю — своего рода метаинформация или рефлекшн — и соответственно код на более высоком уровне.

Хотя, возможно, мой класс фабрики можно относледовать от класса Loki::Factory, что бы заюзать часть функциональности.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 17:17
Оценка:
Здравствуйте, BitField, Вы писали:

BF>Здравствуйте, remark, Вы писали:


R>>Надеюсь хоть кто-то дочитает до конца


BF>Дочитал... Полезное решение..


BF>Вот только есть одна проблема, о которой стоит, наверно, вспомнить...

BF>При реализации классов в статической библиотеке существует вероятность, что они будут таки проигнорированы линкером....

Можно поподробнее, о каких именно классах идёт речь?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 17:32
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Можно передавать через шаблон некоторые аргументы:

__>Бонус небольшой изврат :-D
__>
__>struct Header1 : Header<Header1,
__>                        1,
__>                        Header1Dlg,
__>                        true,
__>                        mpl::list<mpl::long_<'SOME'>, mpl::long_<'_HEA'>, mpl::long_<'DER'> > >
__>{
__>};
__>


Можно. Тут по вкусу. Принипиально ничего не поменяется.
Имхо так более наглядно и явно:
    // Связываем с типом числовое значение
    static const int TYPE = 1;




__>Что насчет автоинкремента номера ?

__>Что-то вроде:
__>
__>template<typename T>
__>struct Header
__>{
__> static const ID = increment_meta_function<T>::value;
__>};
__>



Когда я использовал такое решение идентификаторы хранились или в БД или были связаны с внешними программами. В таком случае явное указание идентификатора не только можно, но и нужно.
Если идентификаторы используются только внутри программы и за её пределы ни во времни, ни в пространстве не выходят, но можно сделать автоикремент. По-моему самое логичное для него место — при регистрации в фабрике. Если они конечно не нужны в компайл-тайм.
Хотя нужны ли будут в таком случае вообще идентификаторы и фабрика? Надо смотреть.



R>>2. Инрастуктура функциональная, расширяемая и "умная"

__>Пока не будут применятся в полную метапрограммирование на шаблонах и на макросах не будет полностью расширяемая
Ну шаблоны тут есть (Header<>, HeaderWrapper<>), в них можно помещать шаблонный код.
Для макросов пока как-то не нашлось применения



R>>... что-то уже до целой статьи дотягивает

__>Приветствуется
Лень


R>>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 17:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Так это, с чего всё начиналось -

А>да, switch'а нет, зато есть std::map, что в плане производительности ещё хуже


Это не совсем с того началось, о чём вы думаете. Это началось с вопроса о саморегистрации.
А если нужна высокая производительность в этом месте, то в фабрике можно использовать упорядоченный vector или сделать тот же switch.

А если у интерфейса IHeader есть несколько виртуальных методов, то это решение будет выигрывать по скорости у С-подхода, т.к. switch (или поиск в упорядоченном vector) будет выполняться только один раз, а не много раз.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Саморегистрация классов в фабрике
От: remark Россия http://www.1024cores.net/
Дата: 17.03.06 17:52
Оценка:
Здравствуйте, rg45, Вы писали:


R>"remark" <38267@users.rsdn.ru> wrote in message news:1788774@news.rsdn.ru...

>> Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.
>> Может кому будет полезно. Или кто выскажет конструктивные замечания.
>>...

R>А что, мне нравится.

R>Конечно слабым местом является то, что идентификаторы нужно назначать в каждом типе руками и, похоже, применительно к тому примеру, от которого родился этот топик, от этого никуда не денешься: в потоке данных хранятся именно числа. А вот в общем случае, ключ мапа можно было бы сделать строковым и загонять туда typeid(Derived).name(), вот это вообще будет хорошее решение.


Не думаю, что в общем случае это будет хорошее решение. Там уже ниже такие замуты пошли про typeid и hash...
По моему опыту обычно идентификаторы либо храняться в БД, либо в файле, либо приходят по сети, либо это названия элементов в XML. Т.е. явное указание идентификатора не минус, а плюс.

Явно его можно не указывать только в том случае, если он не выходит за пределы программы не в пространстве, ни во времени. Тогда стоит вопрос, а нужна ли будет в таком случае вообще фабрика и идентификаторы?

Обычна фабрика нужна, когда тип класса считывают из внешнего источника: БД/XML/socket. А если всё происходит внутри программы, то зачем нужна фабрика и идентификаторы типов???



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Саморегистрация классов в фабрике
От: _nn_  
Дата: 17.03.06 18:08
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, _nn_, Вы писали:


__>>Можно передавать через шаблон некоторые аргументы:

__>>Бонус небольшой изврат :-D
__>>
__>>struct Header1 : Header<Header1,
__>>                        1,
__>>                        Header1Dlg,
__>>                        true,
__>>                        mpl::list<mpl::long_<'SOME'>, mpl::long_<'_HEA'>, mpl::long_<'DER'> > >
__>>{
__>>};
__>>


R>Можно. Тут по вкусу. Принипиально ничего не поменяется.

R>Имхо так более наглядно и явно:
R>
R>    // Связываем с типом числовое значение
R>    static const int TYPE = 1;
R>


Возможно лучше будет функция.
Так можно будет во времени выполнения загружать идентификатор.

__>>Что насчет автоинкремента номера ?

__>>Что-то вроде:
__>>
__>>template<typename T>
__>>struct Header
__>>{
__>> static const ID = increment_meta_function<T>::value;
__>>};
__>>



R>Когда я использовал такое решение идентификаторы хранились или в БД или были связаны с внешними программами. В таком случае явное указание идентификатора не только можно, но и нужно.

R>Если идентификаторы используются только внутри программы и за её пределы ни во времни, ни в пространстве не выходят, но можно сделать автоикремент. По-моему самое логичное для него место — при регистрации в фабрике. Если они конечно не нужны в компайл-тайм.
Значит нужно какое-то универсальное и красивое решение
R>Хотя нужны ли будут в таком случае вообще идентификаторы и фабрика? Надо смотреть.
А как определять разные классы ? По typeid ?
Если можно то лучше без него


R>>>2. Инрастуктура функциональная, расширяемая и "умная"

__>>Пока не будут применятся в полную метапрограммирование на шаблонах и на макросах не будет полностью расширяемая
R>Ну шаблоны тут есть (Header<>, HeaderWrapper<>), в них можно помещать шаблонный код.
R>Для макросов пока как-то не нашлось применения
Значит разработка еще не доросла до библиотечного уровня

R>>>... что-то уже до целой статьи дотягивает

__>>Приветствуется
R>Лень
Не аргумент

R>>>

R>
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Саморегистрация классов в фабрике
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 18.03.06 08:32
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, BitField, Вы писали:


BF>>Вот только есть одна проблема, о которой стоит, наверно, вспомнить...

BF>>При реализации классов в статической библиотеке существует вероятность, что они будут таки проигнорированы линкером....

R>Можно поподробнее, о каких именно классах идёт речь?


Фабрика и классы заголовков (Header1, Header2) находятся в статической библиотеке. Пусть, например, Header1 (все его ф-ции, vtbl, и регистратор) находятся в единице трансляции, после компиляции которой имеет Header1.o[bj]. Он помещается в статическую библиотеку. При линковке этой библиотеки к исполняемому файлу в случае, если ни один из символов, определенных в Header1.o[bj], не используется в других обьектных файлах, линкер имеет полное право игнорировать Header1.o[bj] целиком -- и саморегистрация Header1 не происходит.

Одно из обсуждений этой проблемы http://www.rsdn.ru/Forum/Message.aspx?mid=97459
Автор:
Дата: 09.09.02
Re[3]: Саморегистрация классов в фабрике
От: Аноним  
Дата: 18.03.06 15:00
Оценка: 1 (1) +1
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, remark, Вы писали:


R>>>Решение для типовой задачи, когда есть интерфейс, реализации интерфейса, и реализации создаются фабрикой по некоторому значению (типу реализации). В решении обеспечивается саморегистрация классов реализаций интерфейса в фабрике, т.о. отпадает необходимость в switch'е в фабрике, и решение становиться максимально открытым для расширения.

R>>>Может кому будет полезно. Или кто выскажет конструктивные замечания.

А>>См. Александреску "Современное проектирование...". ИМХО там реализация лучше. А в последних версиях Loki аффтар "творчески переработал" этот кусок.


R>Нет, там другое.

R>Часть функциональности, о которой я говорю там есть. Но только часть, причём не главная. Там нет саморегистрации.
ИМХО, как раз основое (оно же главное) там есть. Добавлена только саморегистрация, что есть довольно сомнительное приобретение. В "классической" реализации фабрики классов есть возможность собрать вызовы Register в одном месте, что очень удобно при большом количестве "продуктов". В твоём же случае, когда тебе понадобиться добавить очередной продукт, придётся обшарить все модули с целью узнать следующее незанятое значение TYPE. А их может быть несколько больше, чем один.
R>Там нет возможности нагружать эту инфроструктуру дополнительной функциоанльностью. То о чём я говорю — своего рода метаинформация или рефлекшн — и соответственно код на более высоком уровне.
Вот тут хотелось бы поподробнее. Смысл фабрики — сокрытие типов. Откуда возьмётся информация?

    IHeader::Ptr h1 = HeaderFactory::create(48);
    h1 ... что дальше? IS_SIMPLE? как?



R>Хотя, возможно, мой класс фабрики можно относледовать от класса Loki::Factory, что бы заюзать часть функциональности.

))))

R>Плюсы:

R>1. Практически нулевое дублирование, что важно для сопровождаемого кода

R>2. Инрастуктура функциональная, расширяемая и "умная"
Loki::Factory
R>3. Сами классы реализаций интерфейсов абсолютно самодостаточные, самоописываемые, т.е. высокая локальность данных и R>функций
Это уж как их реализует пользователь этой фабрики.
R>4. Чтобы добавить новый класс реализации надо просто его описать и его поддержка автоматически появиться везде где R>она должна быть. Чем не может похвастаться традиционный подход — саму реализацию добавил, добавил её поддержку в R>фабрику, добавил её поддержку в интерфейс пользователя, а при загрузке из БД забыл.
Про обратную сторону медали этого удобства я уже писал.

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


Это при условии, что я всё правильно понял.
Re[2]: Саморегистрация классов в фабрике
От: Аноним  
Дата: 18.03.06 15:11
Оценка: +1 :)
Здравствуйте, Аноним, Вы писали:

А>Так это, с чего всё начиналось -

А>да, switch'а нет, зато есть std::map, что в плане производительности ещё хуже
Ты, другой аноним, нашего ремарка не обижай.
Какая тебе производительность?
Библиотеки пишут для увеличения скорости разработки.
Лучше нарисуй-ка мне свой быстрый свитч для неинтегрального типа. Хоть для строки.


P.S. А уменя смайлики отвалились — вставляться не хочут 8(
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.