Декоратор беспорядок - PullRequest
       20

Декоратор беспорядок

0 голосов
/ 24 сентября 2018

У меня проблема с выяснением, правильно ли я использую шаблон декоратора.Предположим, я работаю над консольным приложением.В этом приложении я определил простой интерфейс IConfigPathProvider, который предоставит путь к файлу конфигурации для некоторого класса.

public interface IConfigPathProvider
{
    string GetConfigPath();
}

Путь хранится в разделе appSettings файла app.config консольного приложения.

public class AppSettingsConfigPathProvider : IConfigPathProvider
{
    public string GetConfigPath()
    {
        return System.Configuration.ConfigurationManager.AppSettings["configPath"];
    }
}

Дело в том, что этот путь также зашифрован, поэтому ...

public class DecryptingConfigPathProvider : IConfigPathProvider
{
    private readonly IConfigPathProvider _provider;
    private readonly IStringDecrypter _decrypter;

    public DecryptingConfigPathProvider(IConfigPathProvider provider, 
        IStringDecrypter decrypter)
    {
        _provider = provider ?? throw new ArgumentNullException(nameof(provider));
        _decrypter = decrypter ?? throw new ArgumentNullException(nameof(decrypter));
    }

    public string GetConfigPath()
    {
        var path = _provider.GetConfigPath();
        //decrypting method of IStringDecrypter interface
        return _decrypter.DecryptString(path);
    }
}

Но, подождите: это еще не конец.Я должен добавить определенную часть к пути, чтобы получить его правильно.

public class AppendSectionConfigPathProvider : IConfigPathProvider
{
    private readonly IConfigPathProvider _provider;

    public AppendSectionConfigPathProvider(IConfigPathProvider provider)
    {
        _provider = provider ?? throw new ArgumentNullException(nameof(provider));
    }

    public string GetConfigPath()
    {
        var path = _provider.GetConfigPath();

        return System.IO.Path.Combine(
            System.IO.Path.GetDirectoryName(path),
            "section", 
            System.IO.Path.GetFileName(path));
    }
}

А теперь - почему бы и нет?- давайте добавим некоторые записи.

public class LoggingConfigPathProvider : IConfigPathProvider
{
    private readonly static ILog _log = 
        LogManager.GetLogger(typeof(LoggingConfigPathProvider));

    private readonly IConfigPathProvider _provider;

    public LoggingConfigPathProvider(IConfigPathProvider provider)
    {
        _provider = provider ?? throw new ArgumentNullException(nameof(provider));
    }

    public string GetConfigPath()
    {
        _log.Info("Getting config path...");
        var path = _provider.GetConfigPath();

        _log.Info("Config path retrieved successfully!");
        return path;
    }
}

Разделить и императировать

Конечно, мгновенный результат - это разделение интересов, НО как насчет дополнительной сложности в создании объекта? Вам нужно знать, какой декоратор стоит первым и в каком порядке они должны быть связаны , в противном случае вы получите глючный IConfigPathProvider.

new LoggingConfigPathProvider(
    new AppendSectionConfigPathProvider(
        new DecryptingConfigPathProvider(
            new AppSettingsConfigPathProvider(), 
            decrypter));

И это всего лишь простой поставщик,В довольно сложном приложении вы, вероятно, встретите несколько компонентов с несколькими ссылками ... это может легко привести к кошмару обслуживания.Теперь, это известный недостаток, или я просто использую этот шаблон неправильно?

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Вы не обязательно правы.Вместо того, чтобы украшать объект сразу, сохраните некоторую декоративную схему , проверяемую, ленивую, которую можно преобразовать в необходимый (окончательный, готовый к использованию) объект, вызвав, скажем, .Build(),Просто эскиз кода: obj.DecorateWith<Decorator1>().DecorateWith<Decorator2>().DecorateWith(() => new Decorator3(IContainer.Resolve<SomeWhatArgument> ...).Build().Это определенно усложняет ситуацию, однако, если декорирование - это правильный путь, а ваш проект действительно достаточно большой, чтобы извлечь выгоду из такой высокой абстракции, он решит вашу проблему.

0 голосов
/ 24 сентября 2018

Это известный недостаток.GoF упоминает следующую ответственность Pattern Decorator:

Множество маленьких объектов. Дизайн, который использует Decorator, часто приводит к системам, состоящим из множества маленьких объектов, которые все похожи друг на друга,Объекты отличаются только тем, как они взаимосвязаны, а не их классом или значением их переменных.Хотя эти системы легко настраиваются теми, кто их понимает, их может быть сложно изучить и отладить.

...