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

Ответ

Для создания объектов, тип которых зависит от контекста или входных параметров, я обычно применяю Фабричный метод (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.");

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

Ответ 18+ 🔞

А, ну это же классика, ёпта! Сидишь такой, пишешь код, и тут бац — нужно объекты создавать, а какой именно нужен, заранее нихуя не ясно. Типа, смотри, пользователь в конфиге написал «file» или «console», а ты должен как волшебник из шляпы вытащить правильную реализацию. Пиздец как знакомо.

Вот в таких случаях все умные дядьки в книжках советуют Фабричный метод или Абстрактную фабрику. Первый — это когда ты делегируешь создание объектам-наследникам, типа «ребята, сами решайте, как вас порождать». Второй — когда у тебя целая банда связанных объектов, и их всех нужно создавать согласованно, чтобы, не дай бог, WindowsButton не встал в паре с MacOSCheckbox. Абстрактная фабрика — это уже для серьёзных пацанов, когда архитектура разрослась до овердохуища.

Но честно? Чаще всего хватает простой, блядь, фабрики — не мудрим, просто статический метод, который по какому-то условию возвращает нужный объект. Работает, и мозг не ебёт.

Смотри, вот тебе живой пример на 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"),
        };
    }
}

Видишь эту красоту? switch выражение, всё чётко. Сказали «file» — получи FileLogger. Сказали «console» — на тебе ConsoleLogger. А если какую-то хуйню написали — получите исключение прямо в ебало, разбирайтесь.

Использовать — вообще элементарно, ядрёна вошь:

ILogger logger = LoggerFactory.CreateLogger("file");
logger.Log("Application started.");

И весь твой основной код теперь нихуя не знает про конкретные классы логгеров. Он работает с интерфейсом ILogger. Захотел поменять логику создания или добавить новый тип логгера (например, NetworkLogger) — идёшь в фабрику, дописываешь одну строку в switch, и ни одна другая часть кода даже не чихнёт. Волнение ебать, как удобно!

Вот и вся магия. Никаких сложных паттернов, если не надо. Простая фабрика — и уже жить становится проще, а код чище. Главное — не превращать эту фабрику в божественный объект, который знает всё на свете, а то будет пизда рулю.