14 вересня 2010 р.

"Патерн Вівторка" #6: Фабричний метод (Factory Method)

Уявіть, що ваша аплікація є дуже складною і так склалося, що ви використовуєте два логінг провайдери - один 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.

Немає коментарів:

Дописати коментар