Название: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 13, 2012, 11:19 Взято из QtDesigner.
В приведенном примере - фабрика оболочек(расширений) объектов системы - ExtensionFactory. Например, список свойств объекта является оболочкой объекта. У одного и того же объекта в системе может быть несколько оболочек(расширений) разного плана. Получить их можно с помощью менеджера расширений. Менеджер регистрируюет каждую конкретную фабрику расширений под определенным id фабрики. По id фабрики менеджер определяет с помощью какой конкретной фабрики создавать конкретную оболочку(расширение) объекта. Например, PropertySheetExtension - оболочка, хранящая свойства объекта. ContainerExtension - это оболочка-контейнер объекта и.т.д. В первом прикрепленном файле - собственно фабрика. Чтобы не порождать подклассы фабрик используются шаблонные классы. Во втором прикрепленном файле - менеджер, используемый для регистрации фабрик. В третьем прикрепленном файле пример объектов которые порождаются фабриками. Вот несколько фабрик: Код: typedef ExtensionFactory<QDesignerContainerExtension, QStackedWidget, QStackedWidgetContainer> QDesignerStackedWidgetContainerFactory; Фабрики создаются и регистрируются так: Код: QExtensionManager *mgr = new QExtensionManager(this); Пример использования объектов, порожденных фабриками: Код: ... Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 13, 2012, 11:27 Правда синтаксис функции - qt_extension не могу до сих пор понять. но смысл - manager->extension(object, iid)
т.е. вместо QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget) можно записать так: QDesignerContainerExtension *container = qobject_cast<QDesignerContainerExtension*>(core()->extensionManager()->extension(widget, Q_TYPEID(QDesignerContainerExtension))); Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 14, 2012, 10:43 На мой взгляд предложенная схема обсуждения неудачна. Типа "вот тролли применили паттерн, давайте у них учиться". Никто не спорит, изучение исходников Qt дает больше чем просто использование. Но все-таки просматривая исходники мы не проектируем, не принимаем решений и не несем за них никакой ответственности. Др словами делать самому и смотреть/понимать как делают другие - совсем не одно и то же.
Также возникает "эффект уже написанного". Если уже есть мощные, развитые классы, то другие часто создаются в угоду им. Поэтому трудно оценить объективный эффект паттерна - возможно и без него было бы неплохо. Ну и вообще, мужики сюда заходят отдохнуть, языком почесать, блеснуть познаниями - а Вы им по рогам кучей классов дизайнера.. Ну кто ж будет их учить и Вам отвечать? :) Возвращаясь к фабрике - это один из немногих паттернов с которым все ясно и который трудно спутать с чем-то другим. Обычно "factory" есть и в имени класса. Предполагает набор (хотя бы 2-3 класса) над которым эта фабрика и создается. Типичный пример - набор загрузчиков файлов или набор плагинов. Честно говоря не вижу что тут обсуждать Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 14, 2012, 11:07 ... ;D ;D ;D класс! отличный юмор!Ну и вообще, мужики сюда заходят отдохнуть, языком почесать, блеснуть познаниями - а Вы им по рогам кучей классов дизайнера.. Ну кто ж будет их учить и Вам отвечать? :) ... Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 14, 2012, 11:52 На мой взгляд предложенная схема обсуждения неудачна. Типа "вот тролли применили паттерн, давайте у них учиться". Никто не спорит, изучение исходников Qt дает больше чем просто использование. Но все-таки просматривая исходники мы не проектируем, не принимаем решений и не несем за них никакой ответственности. Др словами делать самому и смотреть/понимать как делают другие - совсем не одно и то же. Также возникает "эффект уже написанного". Если уже есть мощные, развитые классы, то другие часто создаются в угоду им. Поэтому трудно оценить объективный эффект паттерна - возможно и без него было бы неплохо. Ну и вообще, мужики сюда заходят отдохнуть, языком почесать, блеснуть познаниями - а Вы им по рогам кучей классов дизайнера.. Ну кто ж будет их учить и Вам отвечать? :) Возвращаясь к фабрике - это один из немногих паттернов с которым все ясно и который трудно спутать с чем-то другим. Обычно "factory" есть и в имени класса. Предполагает набор (хотя бы 2-3 класса) над которым эта фабрика и создается. Типичный пример - набор загрузчиков файлов или набор плагинов. Честно говоря не вижу что тут обсуждать Это ж ветка - Кладовая готовых решений. Вот нашла решение и разместила его тут. Обсуждать наверно и правда нечего. Если ктото сочтет это полезным - будет использовать. Единственное что я думаю. Ясность моего изложения наверно оставляет желать лучшего. Может быть чего-то и пропустила. Если что пишите. И пример не очень простой для понимания. Хотя есть и посложнее примерчики. Реализация окошка редактирования свойств чего только стоят. Диаграмма на всю стену в офисе получается))) Хотя организовано классно, ибо добавить новый вид свойств, со специфическим редактором оказалось очень легко. Вот сижу ломаю голову как упростить изложение материала) Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 11:10 Еще один пример. Создание окон разного типа.
Окно создается так: ToolWindow::createStandardToolWindow(ToolWindow::PropertyEditor); Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 11:25 Еще один пример. Создание окон разного типа. Несерьезная у них фабрика. Не должен нигде вылазить switch. А inline(ы) вообще так, затычка Окно создается так: ToolWindow::createStandardToolWindow(ToolWindow::PropertyEditor); Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 11:40 Еще один пример. Создание окон разного типа. Несерьезная у них фабрика. Не должен нигде вылазить switch. А inline(ы) вообще так, затычка Окно создается так: ToolWindow::createStandardToolWindow(ToolWindow::PropertyEditor); почему затычка?? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 11:52 почему затычка?? Потому что не пользуемся ToolWindow::CreateStandardToolWindow, который для этого предназначен, а городим еще inline чтобы это же сделать Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 12:10 Смысл фабрики (как я его понимаю) в спекуляции/обыгрывании зарегистрированной мапы. Примеры
Код
Код
В первом случае мы довольно легко можем обойтись switch и (пока) забыть об этом. Однако если возникает второй случай - опять придется городить switch, причем обильный и.т.д Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Akon от Июнь 15, 2012, 12:15 2nata267:
Просьба, вы когда выкладываете решение, поясняйте, зачем оно нужно и, главное, чем оно лучше известных решений. Например, метаобъектная система Qt позволяет сделать так, а на row C++ вы вынуждены будете делать так и т.п. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 12:24 Код
А что вообще такое it->second и разве не it.second в вашем примере? И почему в случае если достигнут конец итератора возвращается 0, а не вставка? а в случае когда НЕ достигнут конец вставка (если я не ошибаюсь) вместо найденного значения?? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 12:26 2nata267: Просьба, вы когда выкладываете решение, поясняйте, зачем оно нужно и, главное, чем оно лучше известных решений. Например, метаобъектная система Qt позволяет сделать так, а на row C++ вы вынуждены будете делать так и т.п. row C++??? what is it? простите мою безграмотность Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: kambala от Июнь 15, 2012, 12:31 думаю имелось в виду raw (чистый или «голый»)
Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 12:32 А что вообще такое it->second и разве не it.second в вашем примере? Просто перепутал точку с ->. Подправил, спасибоrow C++??? what is it? простите мою безграмотность Наверное имеется ввиду "raw" (сырой). И бог с ней, с грамотностью. Лучше знать меньше но основательнее Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 12:42 2nata267: Просьба, вы когда выкладываете решение, поясняйте, зачем оно нужно и, главное, чем оно лучше известных решений. Например, метаобъектная система Qt позволяет сделать так, а на row C++ вы вынуждены будете делать так и т.п. Я стараюсь пояснять для чего нужны примеры. К тому же примеры из жизни и следовательно понятно для чего они нужно. Последний например - это всем известные окошки программ-редакторов (окошки свойств, object inspector и т д). Чем рассматриваемые мной решения лучше? А какие критерии по которым определяется чем лучше или хуже?? И что вы понимаете под "известные решения". Может быть мне они не известны, выкладывайте свои известные решения. Очень интересно их будет сравнить. Если классы в примерах наследуют от qt-шниых QObject, QWidget... следовательно метаобъектная система Qt позволяет сделать так, а не чистый с++, об этом нетрудно догадаться. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 12:44 Может быть обсуждать архитектуру следует другим образом. Ставить задачу, а каждый будет предлагать свое решение. У кого самое красивое - тот и победил). Например, как реализовать такую функциональность приложения как Отмена/Возврат действий пользователя. Всем известно что там применяется паттерн команда. Но это в теории. А подробное решение данной задачи - структура и взаимодействие классов. И так чтобы это решение подходило для многократного использования в различных проектах
Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 12:52 Может быть обсуждать архитектуру следует другим образом. Ставить задачу, а каждый будет предлагать свое решение. У кого самое красивое - тот и победил) Мне кажется так будет гораздо лучше. Не надо так настороженно воспринимать слова Akon - я полагаю он хочет участвовать, но просто не видно как это сделать с таким террором классов Qt который Вы развязали :)Edit: Например, как реализовать такую функциональность приложения как Отмена/Возврат действий пользователя. Всем известно что там применяется паттерн команда. Но это в теории. А подробное решение данной задачи - структура и взаимодействие классов. И так чтобы это решение подходило для многократного использования в различных проектах Дело в том что полное/честное решение этой задачи (undo) весьма сложно, во всяком случае Qt его не предоставляет. Не настаиваю но имеет смысл взять что-то попрощеНазвание: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 13:05 Не настаиваю но имеет смысл взять что-то попроще Например? В моем проекте который я делала, например, заказчик требовал такую функциональнось, которая не была реализована потому что я вообще не представляла как это можно сделать, и поиски в гугле ничего не дали( Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Akon от Июнь 15, 2012, 13:16 Я хочу сказать вот что: я открываю топик - вижу фабрики классов, судя по коду используется Qt. Ну и что, я знаю что такое фабрики классов, для чего они нужны и как реализуются, и для меня это в целом неинтересно. Но! Может быть, вы приводите использование некоторой Qt-фичи, упрощающей реализацию паттерна, и если я не знаю об этой фиче, то мне становится интересно и я читаю топик, в противном случае - пропускаю топик.
Да, конечно raw (а не row). Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 13:18 Например? А я Вас предупреждал что найти подходящий пример "архитектуры" совсем непросто, так что ищите сами :) В моем проекте который я делала, например, заказчик требовал такую функциональнось, которая не была реализована потому что я вообще не представляла как это можно сделать, и поиски в гугле ничего не дали( Ну можно начать с того же примерв Qt и освоить простую технику undo stack. Некоторые (или многие) находятся в счастливой безмятежной уверенности что undo решается как "и все остальное" - ну прочитал ассыстант, взял класс и "попробывал". Однако в случае undo это не так, там действительно "архитектура" - и это тааак не нравится :)Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 13:28 Ну и что, я знаю что такое фабрики классов, для чего они нужны и как реализуются, и для меня это в целом неинтересно. Но! Может быть, вы приводите использование некоторой Qt-фичи, упрощающей реализацию паттерна, и если я не знаю об этой фиче, то мне становится интересно и я читаю топик, в противном случае - пропускаю топик. Я часто ловил себя на мысли что некоторые вещи вроде казались вполне ясными - но оказывается понимались мною весьма поверхностно. Так что повторить и углУбить - точно не помешаетНазвание: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 14:00 Я хочу сказать вот что: я открываю топик - вижу фабрики классов, судя по коду используется Qt. Ну и что, я знаю что такое фабрики классов, для чего они нужны и как реализуются, и для меня это в целом неинтересно. Но! Может быть, вы приводите использование некоторой Qt-фичи, упрощающей реализацию паттерна, и если я не знаю об этой фиче, то мне становится интересно и я читаю топик, в противном случае - пропускаю топик. Да, конечно raw (а не row). Фабрику можно реализовать по разному, это просто одна из версий её реализации. Фабрика + менеджер, регистрирующий каждую конкретную фабрику под определенным id фабрики. По id фабрики менеджер определяет с помощью какой конкретной фабрики создавать конкретный продукт. И кстати называется фабрикой расширений (ExtensionFactory), потому что конкретные продукты являются расширением некоторого объекта, переденного при создании этого продукта. То есть это фабрика оболочек какихто объектов. Если это свойства объекта (PropertySheetExtension), то это оболочка хранящая свойства объекта к примеру. Если это контейнер (ContainerExtension), то это оболочка-контейнер объекта и.т.д. К тому же у одного и тогоже объекта в системе может быть несколько расширений разного плана. Получить их можно с помощью менеджера расширений. Вот в этом фитча собственно и объяснение зачем нужен пример. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 14:47 Я, если позволите, одеяло на свою сторону опять потяну. Вот в случае с виджетами редактора, тут вроде как всё понятно: создали окна и пользуем на протяжении всей жизни программы. Ну может быть за редким исключением создадим пару новых и удалим некоторое, незначительное количество старых. Другими словами, время, затрачиваемое на создание фабрикой объектов, в общем-то не принципиально. Но совсем иная ситуация возникает, когда требуется постоянное создание и удаление объектов. И чем быстрее, тем лучше. В этом случае, фабрика в её традиционном исполнении (хоть с менеджером, хоть и без него) становится вполне себе тяжёлым грузом. Вот вроде по условию задачи - чистой воды фабрика, необходимо создание множества разнотипных объектов по их идентификаторам. Но совсем не подходит такое решение, т.к. скорость важнее. Поэтому попытки написания всякого рода универсальных реализаций паттернов в конечном итоге всё равно сводятся к конкретике, к условиям задачи.
Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 14:52 почему затычка?? Потому что не пользуемся ToolWindow::CreateStandardToolWindow, который для этого предназначен, а городим еще inline чтобы это же сделать функции же встраиваемые, возможно это сделано для удобства читаемости кода, та как определение этих функций идет перед реализацией конструкторов в которых они вызываются. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Авварон от Июнь 15, 2012, 15:30 Я, если позволите, одеяло на свою сторону опять потяну. Вот в случае с виджетами редактора, тут вроде как всё понятно: создали окна и пользуем на протяжении всей жизни программы. Ну может быть за редким исключением создадим пару новых и удалим некоторое, незначительное количество старых. Другими словами, время, затрачиваемое на создание фабрикой объектов, в общем-то не принципиально. Но совсем иная ситуация возникает, когда требуется постоянное создание и удаление объектов. И чем быстрее, тем лучше. В этом случае, фабрика в её традиционном исполнении (хоть с менеджером, хоть и без него) становится вполне себе тяжёлым грузом. Вот вроде по условию задачи - чистой воды фабрика, необходимо создание множества разнотипных объектов по их идентификаторам. Но совсем не подходит такое решение, т.к. скорость важнее. Поэтому попытки написания всякого рода универсальных реализаций паттернов в конечном итоге всё равно сводятся к конкретике, к условиям задачи. Не понял. "медленно" найти фабрику по айдишнику в мапе? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 15:32 Не понял. "медленно" найти фабрику по айдишнику в мапе? Создание объекта.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Авварон от Июнь 15, 2012, 15:42 Не понял. "медленно" найти фабрику по айдишнику в мапе? Создание объекта."Если надо создавать много объектов, то это медленно"? Я правильно экстрагировал мысль? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 15:46 "Если надо создавать много объектов, то это медленно"? Я правильно экстрагировал мысль? Если необходимо постоянное создание множества объектов в предельно сжатые сроки. Желательно вообще не тратить время на создание. В данном случае, решением может послужить кэширование или пул.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 15:48 Я, если позволите, одеяло на свою сторону опять потяну. Вот в случае с виджетами редактора, тут вроде как всё понятно: создали окна и пользуем на протяжении всей жизни программы. Ну может быть за редким исключением создадим пару новых и удалим некоторое, незначительное количество старых. Другими словами, время, затрачиваемое на создание фабрикой объектов, в общем-то не принципиально. Но совсем иная ситуация возникает, когда требуется постоянное создание и удаление объектов. И чем быстрее, тем лучше. В этом случае, фабрика в её традиционном исполнении (хоть с менеджером, хоть и без него) становится вполне себе тяжёлым грузом. Вот вроде по условию задачи - чистой воды фабрика, необходимо создание множества разнотипных объектов по их идентификаторам. Но совсем не подходит такое решение, т.к. скорость важнее. Поэтому попытки написания всякого рода универсальных реализаций паттернов в конечном итоге всё равно сводятся к конкретике, к условиям задачи. оболочка объекта создается только один раз и только по запросу, если она не нужна, то она не создается, затем она регистрируется и при повторном её запросе, мы её не создаем, а используем существующую зарегистрированную. Почему мы проигрываем в быстродействии?? Изза поиска по map?? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 15:50 функции же встраиваемые, возможно это сделано для удобства читаемости кода, та как определение этих функций идет перед реализацией конструкторов в которых они вызываются. Встраиваемые или как - не суть. Если мы создаем объект минуя фабрику, значит мы фактически признаем что никакая это не фабрика. Это ж "крах концепции", а по-простому говоря - обкакались троллиСоздание объекта по ID может быть реализовано всяко и целью фабрики не является (скорее это побочный эффект). А вот когда начинается перебор типа "тот или этот объект должен быть создан" - тогда конечно фабрика. Я, если позволите, одеяло на свою сторону опять потяну. Так уж тяните если взялись :) Изложите условия задачи здесь, подумайте как сформулировать (и не отфутболивать по ссылке), обсудим. А то выходит как-то "а у меня вот в той задаче не вышло" - ну так у всех не все выходило и что с того? Обсуждение все равно практически в тупике, так что живой пример может быть полезен. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 16:13 оболочка объекта создается только один раз и только по запросу, если она не нужна, то она не создается, затем она регистрируется и при повторном её запросе, мы её не создаем, а используем существующую зарегистрированную. Почему мы проигрываем в быстродействии?? Изза поиска по map?? Вероятно возникло недопонимание. Я про map нигде не говорил. Под "созданием" объекта имел ввиду:- поиск типа объекта по идентификатору (map, vector, ещё что-нибудь, без разницы); - выделение памяти под новый объект (оператор new); - инициализация параметров объекта входными данными. Если у Вас "оболочка" объекта создаётся единожды, и другие объекты того же типа не создаются вообще, то получается у Вас совсем не фабрика в моём представлении, а что-то похожее на пул. То есть, создали объект предварительно, если понадобился - изъяли из пула, попользовались, а затем снова вернули назад. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 16:27 Так уж тяните если взялись :) Пытаюсь как могу :)Изложите условия задачи здесь, подумайте как сформулировать (и не отфутболивать по ссылке), обсудим. А то выходит как-то "а у меня вот в той задаче не вышло" - ну так у всех не все выходило и что с того? Обсуждение все равно практически в тупике, так что живой пример может быть полезен. Нет, я не говорил, что не получилось. Как раз и сделал у себя в проекте реализацию фабрики. Но это оказалось медленным решением. Медленным, конечно же относительно, однако в моём случае это употребимо.Суть задачи в обработке поступающих HTTP-запросов на сервер. Я отказался от использования одного лишь парсинга строк, поскольку хотелось максимально абстрагироваться от HTTP синтаксиса. Другими словами, на входе имеем HTTP-запрос в тексте, а на выходе - соответствующие классы самого запроса (GET, POST, HEAD и т.п.) и классы заголовков. Вот тут и поимел снижение производительности, т.к. на создание объектов классов и инициализацию их атрибутов входными значениями уходит относительно много времени. А учитывая, что поставлена задача на обработку 10000 запросов в секунду, имею не шибко нужный результат. Таким образом, традиционная фабрика, которая сейчас у меня реализована, мне не подходит по причине довольно жёстких условий задачи, хотя свою работу она выполняет вполне корректно. Поэтому я и написал свою заметку выше. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 16:43 Суть задачи в обработке поступающих HTTP-запросов на сервер. .. Diffuse, specular. BSP, phong shading и.т.п.- Вам это о чем-то говорит? Полагаю что нет, хотя в моей работе это термины самые базовые. Вот столько же (или еще меньше) у меня понятия о GET, POST, HEAD. Не желаете тратить время на формулировку понятную программисту С++, ну значит и нечего обсуждать. Не навязываюсьНазвание: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 17:01 Diffuse, specular. BSP, phong shading и.т.п.- Вам это о чем-то говорит? Полагаю что нет, хотя в моей работе это термины самые базовые. Вот столько же (или еще меньше) у меня понятия о GET, POST, HEAD. Не желаете тратить время на формулировку понятную программисту С++, ну значит и нечего обсуждать. Не навязываюсь Хм... дело не в нежелании. Согласен, что упустил из виду момент, что Ваша специализация может быть далека от веба. Хочу подчеркнуть, что именно непреднамеренно упустил это из виду. Просто у меня задача специфичная. Впрочем, ситуация, с которой я столкнулся, вполне может быть справедлива и для любого другого протокола, а не только HTTP.Запрос HTTP можно представить в виде двухуровневого дерева классов. Первый уровень - это тип/команда запроса. Второй уровень - это заголовки запроса. Чтобы было понятно, приведу простой пример запроса: Код: GET /index.html HTTP/1.1 Как-то так. Если снова написал непонятно, то наверное мне никак по другому. И, повторюсь, дело не в нежелании :) Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: nata267 от Июнь 15, 2012, 17:26 оболочка объекта создается только один раз и только по запросу, если она не нужна, то она не создается, затем она регистрируется и при повторном её запросе, мы её не создаем, а используем существующую зарегистрированную. Почему мы проигрываем в быстродействии?? Изза поиска по map?? Вероятно возникло недопонимание. Я про map нигде не говорил. Под "созданием" объекта имел ввиду:- поиск типа объекта по идентификатору (map, vector, ещё что-нибудь, без разницы); - выделение памяти под новый объект (оператор new); - инициализация параметров объекта входными данными. Если у Вас "оболочка" объекта создаётся единожды, и другие объекты того же типа не создаются вообще, то получается у Вас совсем не фабрика в моём представлении, а что-то похожее на пул. То есть, создали объект предварительно, если понадобился - изъяли из пула, попользовались, а затем снова вернули назад. Как это другие объекты того же типа не создаются?? к примеру на форме 4 объекта QLabel, QLineEdit, 2 QPushButton. У каждого свой набор свойств, которые загружаются в редактор свойств и для каждого объекта создается своя оболочка "список свойств объекта" и помещается в QMap<IdObjectKey, QObject*> ExtensionMap, где QObject* - это оболочка "список свойств объекта", а IdObjectKey - это ключ, который представляет собой QPair<QString, QObject*>, где QString - id фабрики порождающей данный вид оболочек, QObject* - объект, чью оболочку данного вида мы храним в ExtensionMap Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 17:42 принадлежат первому уровню. Например, класс Request_GET содержит классы: Header_Host, Header_User_Agent, Header_Accept и др. Их в каждом запросе может быть довольно много. Соответственно фабрике приходится напрягаться по полной, прокручивая имеющийся у неё список возможных вариантов при каждом запросе. Потом ещё идёт инициализация вновь созданных объектов входными параметрами, проверка их корректности. И в общем-то выливается всё это в довольно длительное время. Пример: есть фабрика - загрузчик файлов, напр jpg, png, bmp (для простоты). Приходит файл напр yyyyy.xxxкоторый надо загрузить. Если тупенько подряд пробовать все загрузчики - да, медленновато. Это Ваш случай? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 17:43 Как это другие объекты того же типа не создаются?? Я лишь предположил :)к примеру на форме 4 объекта QLabel, QLineEdit, 2 QPushButton. У каждого свой набор свойств, которые загружаются в редактор свойств и для каждого объекта создается своя оболочка "список свойств объекта" и помещается в QMap<IdObjectKey, QObject*> ExtensionMap, где QObject* - это оболочка "список свойств объекта", а IdObjectKey - это ключ, который представляет собой QPair<QString, QObject*>, где QString - id фабрики порождающей данный вид оболочек, QObject* - объект, чью оболочку данного вида мы храним в ExtensionMap Ну а раз всё же есть создание объектов, то это вполне может относиться к тому случаю, на который я указал: поиск по id, создание нового объекта и его инициализация могут быть относительно затратны, исходя из специфики задачи. Безусловно, в Вашем случае с 4-мя виджетами думать о таких мелочах нет необходимости. В моём - необходимость имеется. А вроде бы, казалось, один и тот же паттерн.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 17:53 Пример: есть фабрика - загрузчик файлов, напр jpg, png, bmp (для простоты). Приходит файл напр yyyyy.xxx Похоже. Если применительно к изображениям, то я вынужден сначала по расширению файла пределить тип файла. Затем, создать объект класса загрузчика изображения. Наконец, прочитать параметры изображения (а их довольно много) и создать соответствующие им объекты классов, которые со значениями этих параметров будут работать. Последний пункт в случае с изображениями - глупость, обойтись можно одним классом загрузчика, но именно это мне приходится делать для работы с HTTP.который надо загрузить. Если тупенько подряд пробовать все загрузчики - да, медленновато. Это Ваш случай? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 18:23 Похоже. Если применительно к изображениям, то я вынужден сначала по расширению файла пределить тип файла. Затем, создать объект класса загрузчика изображения. Наконец, прочитать параметры изображения (а их довольно много) и создать соответствующие им объекты классов, которые со значениями этих параметров будут работать. Последний пункт в случае с изображениями - глупость, обойтись можно одним классом загрузчика, но именно это мне приходится делать для работы с HTTP. Это задача отой "оболочки" которая часто называется "inventory". В мапе значения хранятся как указатель на inventory который создан синглтоном. ПримерКод Регистрируемся Код Теперь сваливаем всю черновую работу в инвентарь, напр Код Конечно, если мудаковатый юзер записал jpg как png - это не сработает, придется тупо перебирать до тех пор пока кто-то подойдет. Но так быват редко. Конечно все проверки очень быстрые - никаких классов мы не создаем, просто зовем статик методы. И даже не обязаны линейно перебирать - можно зарядить мапы для типов и расширений. А когда уже "прицелились" - создаем экземпляр. Все эти поиски в фабрику хорошо вписываются Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 18:53 Спасибо. Это очень похоже на то, как реализован QMetaType. Я через него сделал фабрику. Примечательно, что создание первого объекта через его метод construct() выполняется довольно медленно, а последующие вызовы идут значительно быстрее. Похоже, что кэшируются соответствия id конкретным типам классов.
Однако поиск соответствия id к типу класса не является самым затратным. Затратно также создание и инициализация входными параметрами. Конечно, затраты эти обычно даже и не берутся во внимание, но мне приходится. Я думаю о том, чтобы вообще исключить процесс создания объектов классов из фабрики, а забирать уже готовые, созданные ранее и инициализированные параметрами по умолчанию. В этом случае, не потребуется вызывать никаких конструкторов, а нужно будет лишь внести входные значения параметров в уже существующий объект. Естественно, что функционал фабрики по поиску соответствия id к конкретному типу класса должен быть сохранён. После того, как объект, полученный из фабрики, выполнит свою задачу, он должен быть возвращён обратно, чтобы вновь быть использованным в другом запросе. В общем, вроде и фабрика, но с функционалом, похожим на QThreadPool. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 15, 2012, 19:07 В этом случае, не потребуется вызывать никаких конструкторов, а нужно будет лишь внести входные значения параметров в уже существующий объект. Ну не синглтон, т.к. 2 или более ниток. Но никто не мешает зарядить и держать обработчики для всех ниток, напрКод Что "не очень стандартно" но, на мой взгляд, никаких прынцыпов не нарушает :) Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 15, 2012, 20:11 Ну не синглтон, т.к. 2 или более ниток. Но никто не мешает зарядить и держать обработчики для всех ниток, напр Да, почти так я и думаю делать. Единственное, для парсинга запросов буду использовать один тред (в нём же и будет пул готовых объектов запросов и заголовков), а пул тредов уже для обработки этих запросов. Думаю, что это должно положительно сказаться на производительности. Посмотрим.... Что "не очень стандартно" но, на мой взгляд, никаких прынцыпов не нарушает :) Да и пофиг на принципы. Эффективное решение задачи подчас важнее следования стандартам.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 16, 2012, 11:36 Думаю, что это должно положительно сказаться на производительности. Это не имеет отношения к теме, но базовые Qt классы (напр QString) довольно затратны. Вызов new на хорошей кратности часто уже тормоз, а о таких ягодках как QString::split (столь любимых молодежью) неудобно и говорить. Возможно нужна разумная примитивизация (в духе С) Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 16, 2012, 11:52 Это не имеет отношения к теме, но базовые Qt классы (напр QString) довольно затратны. Вызов new на хорошей кратности часто уже тормоз, а о таких ягодках как QString::split (столь любимых молодежью) неудобно и говорить. Возможно нужна разумная примитивизация (в духе С) Тут не поспоришь, так и есть. QString оказался существенным тормозом. Тем более, что используемая им UTF-16 мне совершенно ни к чему. Сейчас я пока применяю QString, и кое где QStringList, но думаю впоследствии перейти либо на QByteArray, либо, если и тот не устроит, ограничиться char'ами.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 19, 2012, 14:48 Из всех вариантов фабрик, которые я видел, больше всего мне импонирует вариант на шаблонах.
"Начинается" фабрика с объявления абстрактного класса конструктора объектов - AbstractObjectConstructor. Хотя данный класс сам по себе ничего и не делает, тем не менее он устанавливает одно из правил формирования фабрикой новых объектов. Следующим по списку идёт ObjectConstructor. Поскольку он является наследником AbstractObjectConstructor, ему уже предопределён тип объекта, который он должен вернуть в методе create(). Внутри же этого метода производится создание не базового класса, а того, что затребован из вне. И наконец - ObjectFactory, суть сама фабрика объектов. Использовать просто: Код
Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 26, 2012, 15:36 В продолжение темы о фабрике на шаблонах. Слегка видоизменил первоначальный вариант, интегрировав логику пула объектов в общий функционал фабрики. Городить огород с отдельным классом не стал, уж больно коряво тот вписывался в фабрику. Функции регистрации и дерегистрации классов не thread-safe, т.к. их вызов производится, соответственно, в начале и в конце работы приложения одним и тем же потоком. Впрочем, по желанию мьютексы добавить не проблема. В тоже время функции пула acquire() и release() мьютексами "прикрыты". Для хранения зарезервированных объектов используется QLinkedList, т.к. любая из вызываемых пулом операций выполнится с ним за O(1), что конечно важно.
Разделение функционала фабрики на классы AWebFactory и AWebConstructor позволяет использовать следующую особенность: Код В данном примере, у нас имеется лишь один класс сокетов AWebEpollSocket, унаследованный от AWebSocket. Таким образом, дабы напрямую использовать пул, минуя при этом фабрику, мы переопределяем соответствующие функции. При этом фабричный функционал конечно же остаётся доступен. Если же нам потребуется добавить новые типы сокетов, и какой-либо из них будет использоваться чаще, нежели другие, то в этом случае возможна реализация функции, например selectConstructor(), которая по указанному идентификатору/ключу класса будет устанавливать указатель _constructor на необходимый для текущей работы класс конструктора посредством вызова AWebFactory::constructor(const Key &key). Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: DmitryM от Июнь 26, 2012, 16:29 Я думаю о том, чтобы вообще исключить процесс создания объектов классов из фабрики, а забирать уже готовые, созданные ранее и инициализированные параметрами по умолчанию. Собственно этом занимается паттерн Prototype.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: DmitryM от Июнь 26, 2012, 16:34 а о таких ягодках как QString::split (столь любимых молодежью) неудобно и говорить. Возможно нужна разумная примитивизация (в духе С) Используй паттерн Builder, для создания строк( как в Java и C#).Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 26, 2012, 16:46 Собственно этом занимается паттерн Prototype. Прототипа как такового в моём случае мало. Мне нужен именно пул готовых одинаковых объектов, инициализированных параметрами по умолчанию. При клонировании всё равно потребуется производить создание нового объекта. Пул же, возвращает уже созданный ранее объект, полностью готовый к использованию. Да, это опережающее требование по отношению к сиюминутному использованию памяти, но в условиях э-э-э... конвейерной генерации новых объектов это решение не выглядит столь уж опрометчиво.Впрочем, на классах сокетов какого-либо заметного ускорения не ощущается. Посмотрю ещё, что будет с классами запросов и заголовков. У них "конвейер" в разы быстрее нужен. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 26, 2012, 16:50 Используй паттерн Builder, для создания строк( как в Java и C#). Возможно. Пока просто у меня использование строк ограничивается лишь сравнением. QLatin1String нормально работает в этом отношении. С char'ами может быть потом что-нибудь подумаю.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 26, 2012, 18:46 Пока мне нечего ответить по существу - любые конструкции хороши если они делают то что надо. Неясно как выбираете объект из пула.
Для хранения зарезервированных объектов используется QLinkedList, т.к. любая из вызываемых пулом операций выполнится с ним за O(1), что конечно важно. А как это будет работать? Стандартная техника переносить из одного списка в другой. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 26, 2012, 20:09 Пока мне нечего ответить по существу - любые конструкции хороши если они делают то что надо. Неясно как выбираете объект из пула. По умолчанию пул не содержит объектов. Можно конечно через конструктор класса AWebConstructor ввести переменную, которая бы указывала сколько объектов пула необходимо предварительно создать, но я не стал этого делать. Всё же, пусть пул сам наполнится необходимым количеством объектов в процессе работы приложения. Но так или иначе, никто не мешает поправить этот момент каждому под собственные нужды, исходя из имеющихся условий.Объект из пула выбирается вызовом функции AWebConstructor::acquire(). Если в пуле нет объектов, она просто создаст новый. А как это будет работать? Стандартная техника переносить из одного списка в другой. Я отказался от такого подхода. Второй список объектов, которые были выданы пулом, в пуле не создаётся. Другими словами, пул после выдачи объекта ничего не знает о судьбе этого объекта. Но в любой момент, когда мы попользовались объектом, мы можем вернуть его в пул при помощи AWebConstructor::release().Я подумал, что хранить пулом два списка в общем-то излишне. Во-первых, затраты на перемещение указателей из списка зарезервированных в список используемых и обратно. Во-вторых, объект, будучи изъят из пула, может быть удалён. Это плохо, пришлось бы задействовать "умные" указатели. В-третьих, пул независим от места создания объекта. Объект может быть создан где угодно и не обязательно в пуле, но при этом в пул может быть без проблем помещён. Вполне вероятно, что я отошёл в сторону от традиционной реализации паттерна пула объектов, но мне показался такой подход очень удобным. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 27, 2012, 18:27 Продолжаем развивать фабрику на шаблонах (ёлки, уже можно версии вводить :) )... На этот раз у меня возникла ситуация, связанная с необходимостью создания объектов классов, унаследованных от общего предка, но имеющихся в единичном экземпляре. Например:
Код Обязательным условием к этому является то, что объекты этих классов должны создаваться через ключ/идентификатор. Другими словами через фабрику. В приложении необходимо использовать лишь указатели на эти объекты, никакой необходимости в их (объектов) клонировании нет. Предыдущая версия фабрики с пулом объектов мне не подходила, поскольку там на каждый вызов acquire() фабрика либо создавала новый объект, либо возвращала один из существующих, коих во внутреннем её контейнере может быть превеликое множество. В новой же задаче формулировалось требование, что каждый из набора Child1, ..., ChildN необходимо создавать лишь в единственном экземпляре. Поскольку обе задачи (фабрика с пулом объектов и фабрика единичных объектов) входят у меня в один проект, я решил совместить весь необходимый функционал в одном наборе классов. Изменения:
Обратите внимание, что установка типа алгоритма работы фабрики производится именно в функции AWebFactory::registerClass(). Это позволяет комбинировать варианты действий для разных наследников одного предка одной и той же фабрики. Не исключаю, что подобное вряд ли будет широко востребовано, но тем не менее имеет право на жизнь. Ну и наконец пару слов о новом AWebObjectConstructor. Тут всё просто: используется "умный" указатель. Если объект будет удалён из вне, то по новому запросу он будет пересоздан вызовом acquire(). Эта же функция возвратит указатель на актуальный объект. Функция release() позволяет заместить имеющийся объект новым из вне. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 27, 2012, 20:38 Слишком вольное выделение/создание объектов мне не нравится (что конечно не означает "неправильно"). Кто-то "на стороне" может создать - и вернуть в фабрику. Проходной двор. Мне кажется надо проводить более последовательную идеологию
- никто не может ни создать ни удалить объект минуя фабрику. Пользователь получает не сами объекты а stub'ы, удаление которых ведет к освобождению объекта - но не удалению. - все созданные объекты известны фабрике в любой момент. Важно иметь возможность влиять на все имеющиеся обработчики Вот напр возникла потребность возвращать уже имеющийся объект независимо от его занятости. Если фабрика контролирует все, реализация выглядит примерно так Код Без всякого накручивания конструкторов, типов и.т.п. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 27, 2012, 22:10 Слишком вольное выделение/создание объектов мне не нравится (что конечно не означает "неправильно"). Кто-то "на стороне" может создать - и вернуть в фабрику. Проходной двор. Мне кажется надо проводить более последовательную идеологию Это Вы про пул объектов, правильно? Ну или про фабрику как у меня, совмещённую с пулом.Для того чтобы пул имел возможность отметить "занятые" объекты, их либо придётся перемещать во вторичный список, либо использовать специальный интерфейс (абстрактный класс), от которого эти объекты должны быть унаследованы. Второй вариант конечно хуже всего. А первый - традиционный пул. Другие варианты мне неизвестны. В моём пуле уязвимым местом (может есть ещё, но для поиска таковых и форум :) ), как Вы справедливо заметили, является помещение объекта обратно в пул. В конце концов можно просто нулевой указатель вставить. Или поместить объект в пул, а затем удалить его по указателю из вне. Над этим можно подумать, либо просто иметь в виду. - никто не может ни создать ни удалить объект минуя фабрику. Пользователь получает не сами объекты а stub'ы, удаление которых ведет к освобождению объекта - но не удалению. Можно пример?- все созданные объекты известны фабрике в любой момент. Важно иметь возможность влиять на все имеющиеся обработчики По сути, это весьма небезопасно. Мало ли чем объект может быть занят. В каком треде он выполняется и т.п.Вот напр возникла потребность возвращать уже имеющийся объект независимо от его занятости. Если фабрика контролирует все, реализация выглядит примерно так Код Без всякого накручивания конструкторов, типов и.т.п. Накручивание конструкторов и типов сделано не просто так (отмечу также факт, что на скорости работы приложения применение шаблонов никак не сказывается). Вот в Вашем примере Вы возвращаете некий Object. Хорошо если все объекты, которые Вы "пропускаете" через фабрику унаследованы от него. А если имеют разных предков, которые в свою очередь к Object не имеют никакого отношения? Что тогда, множественное наследование? Например, мне у себя в проекте пришлось отказаться от использования QObject по той лишь причине, что он весьма тяжёл. Но это наверное плата в Qt за универсальность. Где-то даже видел в кьютишном доке объяснение, почему они не используют шаблоны, а пошли по пути сигнал/слот. Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: Igors от Июнь 28, 2012, 11:45 По сути, это весьма небезопасно. Мало ли чем объект может быть занят. В каком треде он выполняется и т.п. Это столь же опасно/безопасно как и любая реализация возвращающая единичный объектНакручивание конструкторов и типов сделано не просто так (отмечу также факт, что на скорости работы приложения применение шаблонов никак не сказывается). Вот в Вашем примере Вы возвращаете некий Object. Хорошо если все объекты, которые Вы "пропускаете" через фабрику унаследованы от него. А если имеют разных предков, которые в свою очередь к Object не имеют никакого отношения? Что тогда, множественное наследование? "Некий Object" может совсем не быть базовым для классов создаваемых фабрикой. Это класс оболочки (инвентарь). Обычно он делегирует действия к экземпляру фабричного класса. Сами эти классы могут быть слабосвязны или вообще несвязны между собой. Поэтому для каждого выписывается класс оболочки - вот он уже имеет общую базу (Object) и виртуалы. Без этой оболочки дело сводится к пулу(ам). Да, можете создавать по имени, резервировать и.т.п. Но "прогнать" через это какое-то действия (т.е. последовательно пробовать с разными классами фабрики) не получается - нет общих виртуалов Edit: вот Вы пишете Код Тогда как уложить в эту фабрику объекты не-наследники Base? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 28, 2012, 12:28 Это столь же опасно/безопасно как и любая реализация возвращающая единичный объект В моём проекте мне нужны единичные константные объекты. Они не будет меняться, будет лишь куча мест, которые по указателям будут на них ссылаться. Я подумываю над тем, как оптимально вписать константность в AWebObjectConstructor. Если же предполагать, что объекты могут меняться, то конечно с безопасностью, при их (объектов) неаккуратном использовании, могут возникнуть проблемы."Некий Object" может совсем не быть базовым для классов создаваемых фабрикой. Это класс оболочки (инвентарь). Обычно он делегирует действия к экземпляру фабричного класса. Сами эти классы могут быть слабосвязны или вообще несвязны между собой. Поэтому для каждого выписывается класс оболочки - вот он уже имеет общую базу (Object) и виртуалы. Я понял. Это по сути мои классы конструкторов (сам AWebAbstractConstructor и его наследники). То есть в Вашем варианте фабрика должна возвращать именно их? Это будет потеря индивидуальности интерфейса доступа к объектам. Да, можно возвращать различные интерфейсы по идентификаторам классов, но потребует в свою очередь "ручного" приведения их типов (ведь абсолютно все возможные варианты действий через виртуальные функции одного предка не опишешь). В моём варианте, корректность приведения типов отслеживается ещё на уровне компиляции, а унифицированного интерфейса действий вполне достаточно.Без этой оболочки дело сводится к пулу(ам). Да, можете создавать по имени, резервировать и.т.п. Но "прогнать" через это какое-то действия (т.е. последовательно пробовать с разными классами фабрики) не получается - нет общих виртуалов Здесь не очень понятно.Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 28, 2012, 12:30 Edit: вот Вы пишете Никак, это фабрика наследников. Если нужно складывать всё подряд, то должна быть другая реализация.Код Тогда как уложить в эту фабрику объекты не-наследники Base? Название: Re: Обсуждение архитектуры приложения. Пример с фабричным методом Отправлено: alexis031182 от Июнь 29, 2012, 15:31 ... QScopedPointer решает проблему с удалением объекта из вне.В моём пуле уязвимым местом (может есть ещё, но для поиска таковых и форум :) ), как Вы справедливо заметили, является помещение объекта обратно в пул. В конце концов можно просто нулевой указатель вставить. Или поместить объект в пул, а затем удалить его по указателю из вне. Над этим можно подумать, либо просто иметь в виду. ... |