Какой паттерн использовать для создания сущности в зависимости от контекста?

«Какой паттерн использовать для создания сущности в зависимости от контекста?» — вопрос из категории Паттерны, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для создания объектов, тип которых зависит от контекста или входных параметров, я обычно применяю Фабричный метод (Factory Method) или Абстрактную фабрику (Abstract Factory).

Фабричный метод отлично подходит, когда логика создания инкапсулирована в подклассах. Абстрактная фабрика — когда нужно создавать семейства связанных объектов.

На практике, для простого контекстного создания, я часто использую простую фабрику (Simple Factory). Вот пример на C#, где в зависимости от типа формата создается соответствующий логгер:

public interface ILogger
{
    void Log(string message);
}

public class FileLogger : ILogger
{
    public void Log(string message)
    {
        File.AppendAllText("app.log", message);
    }
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"LOG: {message}");
    }
}

public static class LoggerFactory
{
    public static ILogger CreateLogger(string loggerType)
    {
        return loggerType.ToLower() switch
        {
            "file" => new FileLogger(),
            "console" => new ConsoleLogger(),
            _ => throw new ArgumentException("Unsupported logger type"),
        };
    }
}

// Использование
ILogger logger = LoggerFactory.CreateLogger("file");
logger.Log("Application started.");

Этот подход отделяет код, использующий логгер, от конкретных классов логгеров, упрощая расширение и тестирование.