Menu
CoddyTech

Паттерн Factory

Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy. Урок 53 из 70.

Фабричный паттерн — это порождающий паттерн, который делегирует создание объектов отдельному методу или классу. Вместо того чтобы напрямую использовать new в своём коде, вы просите фабрику создавать объекты за вас. Это централизует логику создания и делает ваш код более гибким.

Рассмотрим сценарий, в котором вам нужно создавать разные типы документов. Без фабрики ваш код оказывается тесно связан с конкретными классами:

// Без Factory — разбросанная логика создания
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

Фабрика инкапсулирует это принятие решений в одном месте:

public interface IDocument
{
    void Open();
}
public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
    public IDocument Create(string type)
    {
        switch (type)
        {
            case "pdf":
                return new PdfDocument();
            case "word":
                return new WordDocument();
            default:
                throw new ArgumentException("Unknown type");
        }
    }
}

Теперь клиентский код просто запрашивает то, что ему нужно, не зная конкретных классов:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // Открытие PDF

Паттерн «Фабрика» особенно полезен, когда позже нужно добавлять новые типы. Добавление SpreadsheetDocument требует изменений только в фабрике, а не во всех местах, где создаются документы. Такое разделение упрощает поддержку и тестирование кодовой базы.

challenge icon

Задание

Легко

Давайте создадим систему уведомлений с использованием паттерна «Фабрика». Вместо того чтобы напрямую создавать разные типы уведомлений по всему коду, вы централизуете логику создания в классе-фабрике, который решает, какое уведомление создать, на основе простого строкового идентификатора.

Вы организуете код в трёх файлах:

  • Notification.cs: Определите интерфейс INotification в пространстве имён Notifications с единственным методом Send(string message), который возвращает строку. Затем создайте три класса, реализующих этот интерфейс:
    • EmailNotification — возвращает "Email: {message}"
    • SmsNotification — возвращает "SMS: {message}"
    • PushNotification — возвращает "Push: {message}"
  • NotificationFactory.cs: Создайте класс NotificationFactory в том же пространстве имён с методом Create(string type), который возвращает соответствующий INotification в зависимости от строкового значения type:
    • "email" возвращает EmailNotification
    • "sms" возвращает SmsNotification
    • "push" возвращает PushNotification
    Для любого нераспознанного типа по умолчанию возвращайте EmailNotification.
  • Program.cs: Объедините всё, создав экземпляр фабрики и используя его для создания уведомлений на основе входных данных. Фабрика принимает все решения о том, какой конкретный класс создать.

Вы получите два входных значения:

  • Тип уведомления (например, sms)
  • Сообщение для отправки (например, Your order has shipped)

Используйте фабрику, чтобы создать соответствующий тип уведомления, затем вызовите его метод Send с сообщением и выведите результат.

Например, если входными данными являются push и Meeting in 5 minutes, результатом должен быть:

Push: Meeting in 5 minutes

Обратите внимание, что основной код никогда не использует new EmailNotification() или что-либо подобное — он просто запрашивает у фабрики то, что ему нужно. Если позже вы добавите SlackNotification, вам потребуется обновить только фабрику, а не каждое место, где создаются уведомления!

Попробуйте сами

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // Прочитать ввод
        string type = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: Создать экземпляр NotificationFactory

        // TODO: Использовать фабрику для создания соответствующего уведомления

        // TODO: Вызвать метод Send и вывести результат
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C#