24 марта 2025 г. (изменено: 24 марта 2025 г.)
Канал: @cherkashindev
🏗️ Как используется паттерн простая фабрика в исходниках хромиума
Почти год назад я говорил, что паттерн “простая фабрика” используется в исходниках хромиума, и вот у меня ||появилось желание|| дошли руки написать об этом.
Этот паттерн используется в реализации всем нам знакомого (кроме бэкендеров) метода 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