24 марта 2025 г. (изменено: 24 марта 2025 г.)

Канал: @cherkashindev

1 669

🏗️ Как используется паттерн простая фабрика в исходниках хромиума

Почти год назад я говорил, что паттерн “простая фабрика” используется в исходниках хромиума, и вот у меня ||появилось желание|| дошли руки написать об этом.

Этот паттерн используется в реализации всем нам знакомого (кроме бэкендеров) метода document.createElement('div').

Вместо длинного списка switch/case у нас тут словарь, где по имени тега выбирается функция-конструктор и сразу вызывается.

Код целиком можно посмотреть вот здесь 🔗.

 
// html_element_factory.cc
 
static void CreateHTMLFunctionMap() {
  DCHECK(!g_html_constructors);
  g_html_constructors = new HTMLFunctionMap;
  
  // таблица соответствий тегов и функций-конструкторов
  static const CreateHTMLFunctionMapData data[] = {
 // тут конструкторы всех тегов div/span/ul/li/button/h1...
    { html_names::kDivTag, HTMLDivConstructor },
    { html_names::kSpanTag, HTMLSpanConstructor },
    { html_names::kMainTag, HTMLMainConstructor },
    { html_names::kUlTag, HTMLUlConstructor },
    { html_names::kLiTag, HTMLLiConstructor },
    { html_names::kButtonTag, HTMLButtonConstructor },
    { html_names::kCanvasTag, HTMLCanvasConstructor },
    { html_names::kH1Tag, HTMLH1Constructor },
    // .... и так далее
  };
 
  for (size_t i = 0; i < std::size(data); i++)
    g_html_constructors->Set(data[i].tag.LocalName(), data[i].func);
}
 
// функция — фабрика элементов
HTMLElement* HTMLElementFactory::Create(
    const AtomicString& local_name,
    Document& document,
    const CreateElementFlags flags) {
  if (!g_html_constructors)
    CreateHTMLFunctionMap();
  
  // находим функцию-конструктор по имени тега
  auto it = g_html_constructors->find(local_name);
  if (it == g_html_constructors->end())
    return nullptr;
  HTMLConstructorFunction function = it->value;
  
  // создаем элемент
  return function(document, flags);
}

Но это не самое интересное 🕵️‍♂️.

Я достаточно долго искал этот код на гитхабе. ||И не потому что мне было плохо, когда я пытался читать C++ код.|| Я видел, что HTMLELementFactory::Create вызывается, но описания самой функции в коде нет.

Дело в том, что файл html_element_factory.cc, часть которого я привел выше — генирируется при билде. Я написал нескольким разработчикам хромиума, и пара из них скинула мне вот эту ссылку, где я смог посмотреть все исходники, включая сгенирированные.

А генирируется html_element_factory.cc на основе:

  • 📜 <HTMLTagNames.in> — списка тегов
  • 🏗️ ElementFactory.cpp.tmpl — шаблон файла фабрики

@cherkashindev

👍 12 3 🔥 3