У меня проблема с выяснением, правильно ли я использую шаблон декоратора.Предположим, я работаю над консольным приложением.В этом приложении я определил простой интерфейс 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));
И это всего лишь простой поставщик,В довольно сложном приложении вы, вероятно, встретите несколько компонентов с несколькими ссылками ... это может легко привести к кошмару обслуживания.Теперь, это известный недостаток, или я просто использую этот шаблон неправильно?