Уявіть, що ваша аплікація є дуже складною і так склалося, що ви використовуєте два логінг провайдери – один Log4Net та інший Enterprise.Logging. Ваш колега догадався помістити вибір провайдера прямо у конфіг файл. Так як ви всю логіку логування абстрагуєте за інтерфейсом ILogger, то вам б також хотілося приховати специфіку створення конкретного провайдера та винести її в окремий клас.

Фабричний Метод

Як на мене то цей дизайн патерн є одним із найбільш відомих і найпростіших. Я переконаний, що більшість читачів бачили його багато раз. Завдання Фабричного Методу полягає в прихованні конкретного класу, що має бути створений та повернений під виглядом спільної абстракції. Якщо в метод передаються параметри, від яких залежить який клас буде створено, то такий Фабричний Метод називають Параметризованим Фабричним Методом.

В нашому прикладі, класи що мають бути створені є Log4NetLogger та EnterpriseLogger, які імплементують ILogger, який широко використовується у нас в аплікації.

public interface ILogger
{
void LogMessage(string message);
void LogError(string message);
void LogVerboseInformation(string message);
}

Як можна здогадуватися, може статися що в майбутньому нам знадобиться додати ще декілька провайдерів логування (мало чого). Як ми уже згадували вирішення приймається на основі того, що є у файлі конфігурації. Щоб не показувати, який клас ми створюємо ми делегуємо цю роботу до LoggerProviderFactory. Ось використання:

public static void Run()
{
var providerType = GetTypeOfLoggingProviderFromConfigFile();
ILogger logger = LoggerProviderFactory.GetLoggingProvider(providerType);
logger.LogMessage("Hello Factory Method Design Pattern.");
}

private static LoggingProviders GetTypeOfLoggingProviderFromConfigFile()
{
return LoggingProviders.Log4Net;
}

То що ж ми отримуємо від методу GetLoggingProvider є об’єктом реалізуючим потрібний інтерфейс. Фабричний Метод вирішує яикй із конкретних класів створювати на основі вхідного параметру, в нашому випадку це енам.

А ось реалізація Фабричного Методу:

public class LoggerProviderFactory
{
public static ILogger GetLoggingProvider(LoggingProviders logProviders)
{
switch (logProviders)
{
case LoggingProviders.Enterprise:
return new EnterpriseLogger();
case LoggingProviders.Log4Net:
return new Log4NetLogger();
default:
return new EnterpriseLogger();
}
}
}

Оскільки моя хардкоджена конфігурація повертає Log4Net і оскільки імплементація методу LogMessage виглядає приблизно так:

public void LogMessage(string message)
{
Console.WriteLine(string.Format("{0}: {1}", "Log4Net", message));
}

Я отримую наступний вивід:
Log4Net: Hello Factory Method Design Pattern.