- Регистрация
- 03.05.2016
- Сообщения
- 912
- Благодарностей
- 650
- Баллы
- 93
Всем привет, с вами Дмитрий, и моя статья:
Фабричный метод в C# простыми словами (но это не точно)
Предыстория
Наконец-то я добрался до изучения паттернов проектирования. С «Фабричным методом» я был знаком уже давно, но честно признаюсь — до конца не понимал, когда и зачем его применять.
Сейчас, когда картинка сложилась в моей голове, как будто бы я стал его понимать, но возможно я ошибаюсь
Ключевым моментом в понимание для меня стало более глубокое погружение в работу с интерфейсами в C#.
Представьте ситуацию: у нас есть задача, которая имеет одну большую логику работы для разных объектов и периодически добавляются новые объекты. На помощь нам приходят интерфейсы, в которых будет реализована работа этих больших и сложных объектов, для каждого своя. Но в свою очередь эти большие объекты требуют других дополнительных объектов или подготовок перед использованием. И вот именно здесь нам поможет паттерн Фабричный метод.
Немного непонятной теории
Фабричный метод (Factory Method) — это порождающий паттерн, который определяет интерфейс для создания объектов некоторого класса, но непосредственное решение о том, объект какого класса создавать происходит в подклассах. То есть паттерн предполагает, что базовый класс делегирует создание объектов классам-наследникам.
Если сказать проще:
Мы один раз пишем общую логику работы, а для каждого конкретного объекта интерфейса можем подключать свою реализацию через фабрики. Причем таких объекты мы можем подключить сколько угодна и когда угодно, при этом не меняя общей логики.
Практика
Ну что ж, с теорией мы разобрались, очень интересно, но ничего не понятно.
Теперь переходим к практике. Представим, что мы пишем парсер для маркетплейсов.
Этап первый — общий интерфейс
Маркетплейсов у нас много, а логика парсинга у всех будет одна. Поэтому мы создадим общий интерйфес IParser.
Он у нас пока что будет простенький и будет парсить только заголовки и цены товаров на странице и выводить это в лог.
Сейчас он содержит только свойства:
Name - имя парсера;
BaseUrl - урл главной маркетплейса;
TitelXpath - xPath для заголовка товара;
PriceXpath - xPath для цены товара);
Для примера этого хватит, но в дальнейшем по ходу необходимости новых задач, мы сможем его расширить и добавить новые свойства и методы
Теперь реализуем интерфейс для конкретных Маркетплейсов.
Ozon:
WB:
Отлично — у нас есть общий интерфейс и конкретные реализации.
Этап второй — фабрика
Теперь создадим абстрактную фабрику MainFactory. Она будет отвечать только за одно — создание объекта парсера (IParser).
А для каждого маркетплейса сделаем свою фабрику, через MainFactory.
Пояснительная: Мы создаем объекты new ParserOzon() или new ParserWB(), но у обоих возвращаем IParser.
Ozon
WB
Этап третий — общая логика парсинга
Теперь напишем общую логику, которая будет использовать фабрики.
Сделаем словарь фабрик Dictionary<string, Func<IParser>>, чтобы по имени выбрать нужный маркетплейс.
После набросаем общую логику на примере ZennoPoster:
1) Открываем главную сайта Маркетплейса
2) Собираем список текстов и цен на странице
3) Выводим в лог
На этом у нас все, подведем итоги.
Итоги.
Собственно, а зачем мы это все делали? Можно же было сделать все гораздо проще!
Да, можно сделать проще, но мы заложили хороший фундамент для будущего:
Еще раз, но с моими комментариями на видео:
Git:
github.com
Фабричный метод в C# простыми словами (но это не точно)
Предыстория
Наконец-то я добрался до изучения паттернов проектирования. С «Фабричным методом» я был знаком уже давно, но честно признаюсь — до конца не понимал, когда и зачем его применять.
Сейчас, когда картинка сложилась в моей голове, как будто бы я стал его понимать, но возможно я ошибаюсь

Ключевым моментом в понимание для меня стало более глубокое погружение в работу с интерфейсами в C#.
Представьте ситуацию: у нас есть задача, которая имеет одну большую логику работы для разных объектов и периодически добавляются новые объекты. На помощь нам приходят интерфейсы, в которых будет реализована работа этих больших и сложных объектов, для каждого своя. Но в свою очередь эти большие объекты требуют других дополнительных объектов или подготовок перед использованием. И вот именно здесь нам поможет паттерн Фабричный метод.
Немного непонятной теории
Фабричный метод (Factory Method) — это порождающий паттерн, который определяет интерфейс для создания объектов некоторого класса, но непосредственное решение о том, объект какого класса создавать происходит в подклассах. То есть паттерн предполагает, что базовый класс делегирует создание объектов классам-наследникам.
Если сказать проще:
- у нас есть общая логика работы (например, интерфейс или абстрактный класс);
- а вот конкретные «детали сборки» мы доверяем фабрике.
- клиентский код работает только с интерфейсами (то есть использует общую логику, не зная деталей реализации);
- создание конкретных экземпляров «спрятано» за фабричными методами (они подсовывают нужные объекты в общую логику).
Мы один раз пишем общую логику работы, а для каждого конкретного объекта интерфейса можем подключать свою реализацию через фабрики. Причем таких объекты мы можем подключить сколько угодна и когда угодно, при этом не меняя общей логики.
Практика
Ну что ж, с теорией мы разобрались, очень интересно, но ничего не понятно.
Теперь переходим к практике. Представим, что мы пишем парсер для маркетплейсов.
Этап первый — общий интерфейс
Маркетплейсов у нас много, а логика парсинга у всех будет одна. Поэтому мы создадим общий интерйфес IParser.
Он у нас пока что будет простенький и будет парсить только заголовки и цены товаров на странице и выводить это в лог.
Сейчас он содержит только свойства:
Name - имя парсера;
BaseUrl - урл главной маркетплейса;
TitelXpath - xPath для заголовка товара;
PriceXpath - xPath для цены товара);
Для примера этого хватит, но в дальнейшем по ходу необходимости новых задач, мы сможем его расширить и добавить новые свойства и методы
C#:
public interface IParser
{
string Name { get; }
string BaseUrl { get; }
string TitelXpath { get; }
string PriceXpath { get; }
}
Ozon:
C#:
public class ParserOzon : IParser
{
public string Name => "Ozon";
public string BaseUrl => "https://www.ozon.ru/";
public string TitelXpath => "//div[contains(@class, 'root')]//a//span";
public string PriceXpath => "//div[contains(@class, 'root')]//span[contains(@class, 'Headline')]";
}
C#:
public class ParserWB : IParser
{
public string Name => "Wildberries";
public string BaseUrl => "https://www.wildberries.ru/";
public string TitelXpath => "//span[@class='product-card__name']";
public string PriceXpath => "//ins[contains(@class, 'price__lower-price')]";
}
Этап второй — фабрика
Теперь создадим абстрактную фабрику MainFactory. Она будет отвечать только за одно — создание объекта парсера (IParser).
C#:
public abstract class MainFactory
{
/// <summary>
/// Создатель фабрики.
/// </summary>
/// <returns></returns>
public abstract IParser Create();
}
Пояснительная: Мы создаем объекты new ParserOzon() или new ParserWB(), но у обоих возвращаем IParser.
Ozon
C#:
public class FactoryOzon : MainFactory
{
public override IParser Create()
{
return new ParserOzon();
}
}
C#:
public class FactoryWB : MainFactory
{
public override IParser Create()
{
return new ParserWB();
}
}
Теперь напишем общую логику, которая будет использовать фабрики.
Сделаем словарь фабрик Dictionary<string, Func<IParser>>, чтобы по имени выбрать нужный маркетплейс.
После набросаем общую логику на примере ZennoPoster:
1) Открываем главную сайта Маркетплейса
2) Собираем список текстов и цен на странице
3) Выводим в лог
C#:
// Работа с Фабрикой
var parserName = project.Variables["parserName"].Value;
var factories = new Dictionary<string, Func<IParser>>()
{
{ "WB", () => new FactoryWB().Create() },
{ "Ozon", () => new FactoryOzon().Create() },
};
if (!factories.TryGetValue(parserName, out var factory))
throw new ArgumentException("Неизвестный Маркетплейс для парсинга: " + parserName);
var parser = factory();
// Логика парсинга
// Открываем главную сайта Маркетплейса
var tab = instance.ActiveTab;
project.SendInfoToLog("Начинаем парсить: " + parser.Name);
Thread.Sleep(500);
project.SendInfoToLog("Заходим на сайт: " + parser.BaseUrl);
tab.Navigate(parser.BaseUrl);
tab.WaitDownloading();
// Собираем список текстов и цен на странице
project.SendInfoToLog("Собираем данные!");
var titels = tab.FindElementsByXPath(parser.TitelXpath).ToArray();
var prices = tab.FindElementsByXPath(parser.PriceXpath).ToArray();
project.SendInfoToLog("Собрали данных: " + titels.Length);
project.SendInfoToLog("Выводим данные:");
// Выводим в лог
for (var i = 0; i < titels.Length; i++)
{
var titel = titels[i].InnerText;
var price = prices[i].InnerText;
project.SendInfoToLog($"{i + 1} | {titel}. Цена: {price}");
}
project.SendInfoToLog("Закончили парсинг!");
Итоги.
Собственно, а зачем мы это все делали? Можно же было сделать все гораздо проще!
Да, можно сделать проще, но мы заложили хороший фундамент для будущего:
- Захотели добавить новый маркетплейс (например, Яндекс.Маркет) → пишем новый класс, создаём фабрику — и ничего не ломаем в общей логике.
- Появилась задача с авторизацией или другой сложной логикой → переносим её в фабрику, не нагружая IParser и общую логику.
Еще раз, но с моими комментариями на видео:
Git:
GitHub - kdanzp/FactoryMethod
Contribute to kdanzp/FactoryMethod development by creating an account on GitHub.

Вложения
-
10,5 КБ Просмотры: 2
Последнее редактирование: