Разумно ли использовать Factory Pattern для создания экземпляров всех виджетов? - PullRequest
2 голосов
/ 21 июля 2011

Я пытался использовать для реализации стиля и рендеринга в моем небольшом инструментарии GUI, используя Factory Pattern, и затем эта безумная идея поразила меня. Почему бы не использовать шаблон фабрики для всех виджетов?

Прямо сейчас я думаю о чем-то в стиле:

Widget label = Widget::create("label", "Hello, World");
Widget byebtn = Widget::create("button", "Good Bye!");

byebtn.onEvent("click", &goodByeHandler);

Новые типы виджетов будут регистрироваться с помощью функции, подобной Widget::register(std::string ref, factfunc(*fact))

Что бы вы сказали о плюсах и минусах этого метода?

Я бы поставил на то, что при использовании std::map<std::string> проблем с производительностью почти не возникает, поскольку он используется только при настройке.

И да, простите меня за то, что я был поврежден JavaScript и любыми возможными синтаксическими ошибками в моем C ++, поскольку это было довольно давно, с тех пор как я использовал этот язык.


Краткое изложение плюсов и минусов

Плюсы

  • Было бы легко загружать новые виджеты динамически из файла
  • Виджеты можно легко заменить во время выполнения (это также может помочь в модульном тестировании)
  • Обращение к динамичным людям

Минусы (и возможные решения)

  • Не проверено во время компиляции (Можно написать собственную проверку во время сборки. JS / Python / назвать его, также не проверяется во время компиляции; и я полагаю, что разработчики вполне нормально обходятся без него)
  • Возможно, менее производительный (Не нужно создавать виджеты постоянно. Карты строк не будут использоваться все время , а скорее при создании виджета и регистрации обработчиков событий)
  • Up / Downcasting hell (Обеспечьте обычное создание экземпляров класса, где это необходимо)
  • Возможность усложнить настройку виджетов (параметры виджета могут быть одинаковыми)

Мой GUI Toolkit находится на ранних стадиях, ему не хватает довольно много на стороне планирования. И так как я не привык делать каркасы GUI, вероятно, есть много вопросов / design решений , которых у меня еще нет,

Прямо сейчас я не вижу, чтобы виджеты были бы слишком разными по своему набору методов, но, скорее всего, это было бы просто потому, что я еще не рассмотрел более продвинутые виджеты.

Спасибо всем за ваш вклад!

Ответы [ 3 ]

1 голос
/ 21 июля 2011

Я бы посоветовал против , используя string в качестве ключа, и предложил бы реальный метод для каждого подтипа.

class Factory
{
public:
  std::unique_ptr<Label> createLabel(std::string const& v);
  std::unique_ptr<Button> createButton(std::string const& v, Action const* a);
};

Это имеет несколько преимуществ:

  • Проверено компилятором, вы можете неправильно ввести строку, но вы не можете получить работающую программу с ошибочным методом
  • Более точный тип возврата и, следовательно, нет необходимости в повышении (и всех его проблемах)
  • Более точные параметры, для не всех элементов требуется одинаковый набор параметров

Как правило, это делается для настройки. Если Factory является абстрактным интерфейсом, то у вас может быть несколько реализаций (Windows, GTK, Mac), которые по-разному их создают.

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

Примечание: с точки зрения производительности, виртуальные функции намного быстрее, чем поиск по карте с помощью строкового ключа

1 голос
/ 21 июля 2011

Плюсы

  • Было бы легко прочитать виджеты из файла или другого внешнего источника и создать их по их именам.

Против

  • Было бы легко передать неправильное имя типа в Widget :: create, и вы получите ошибку только во время выполнения.
  • У вас не будет доступа к API, зависящему от виджета, без снижения производительности - то есть еще одного источника ошибок во время выполнения.
  • Может быть не так легко найти все места, где вы создаете виджет определенного типа.

Почему бы не получить лучшее из обоих миров, разрешив создание виджетов как с обычными конструкторами, так и с фабрикой?

1 голос
/ 21 июля 2011

Я думаю, что это не очень интуитивно понятно.Я бы предпочел разрешить прямой доступ к классам.Вопрос здесь в том, почему вы хотите иметь это таким образом.Есть ли техническая причина?У вас есть более высокий уровень абстракции над "реальными классами", которые содержат виджеты?Например, у вас есть чисто виртуальные классы для внешнего API, а затем класс реализации?Но трудно сказать, хорошо ли это, не зная, как настроена ваша библиотека, но я сам не большой поклонник фабрик, если они вам действительно не нужны.Если у вас есть более высокий уровень абстракции и вы хотите эту фабрику, взгляните на irrlicht.Он использует чисто виртуальные классы для API, а затем «классы реализации».Фабрика выбирает правильную реализацию в зависимости от выбранного рендерера (directx, opengl, software).Но они не идентифицируют искомый класс строкой.Это то, что я действительно не буду делать в C ++.Просто мои 2 цента.

...