弄清楚我是否以正确的方式使用装饰器模式时遇到问题。假设我正在开发控制台应用程序。在此应用程序中,我定义了一个简单的IConfigPathProvider接口,该接口将提供某个类的配置文件路径。
public interface IConfigPathProvider
{
string GetConfigPath();
}
该路径存储在控制台应用程序的app.config文件的appSettings部分中。
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;
}
}
划分和影响
当然,即时结果是关注点分离, BUT 那么实例化对象所增加的复杂性又如何呢? 您需要知道哪个装饰器首先出现,以及应该按什么顺序链接,否则,您将遇到一个有问题的IConfigPathProvider。
new LoggingConfigPathProvider(
new AppendSectionConfigPathProvider(
new DecryptingConfigPathProvider(
new AppSettingsConfigPathProvider(),
decrypter));
这只是一个简单的提供程序。在一个相当复杂的应用程序中,您可能会遇到具有多个引用的多个组件...这很容易导致维护噩梦。现在,这是一个众所周知的缺点,还是我只是以错误的方式使用了这种模式?
答案 0 :(得分:1)
这是一个众所周知的缺点。 GoF提到了装饰者模式的以下责任。
很多小物件。使用Decorator的设计通常会导致系统 由许多看起来相似的小物体组成。对象仅不同 它们相互联系的方式,而不是他们的阶级或价值 他们的变量。尽管这些系统很容易被那些 了解它们,可能很难学习和调试。
答案 1 :(得分:0)
您不一定正确。与其立即装饰对象,不如保持某种可验证的惰性的装饰shema ,可以通过调用{例如{},将其转换为所需的(最终的,立即可用的)对象。 1}}。只是一个代码草图:.Build()
。它无疑使事情变得更加困难,但是,只要装饰是正确的方法,并且您的项目确实足够大,可以从如此高的抽象度中受益,它将解决您的问题。