当前位置: 首页 > 知识库问答 >
问题:

装饰图案杂物

扶隐水
2023-03-14

我有一个问题,如果我使用的装饰模式是正确的方式。让我们假设我正在处理一个控制台应用程序。在这个应用程序中,我定义了一个简单的IConfigPathProvider接口,它将提供某个类的配置文件路径。

public interface IConfigPathProvider
{
    string GetConfigPath();
}
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;
    }
}

当然,即时的结果是关注点的分离,但是实例化对象时增加的复杂性呢?您需要知道哪个decorator首先出现,以及它们应该按什么顺序链接,否则您最终将得到一个有缺陷的IconfigPathProvider。

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

而这只是一个简单的提供者。在相当复杂的应用程序中,您可能会遇到具有多个引用的多个组件...这很容易导致维护噩梦。现在,这是一个众所周知的缺点还是我只是以错误的方式使用了这个模式?

共有1个答案

扶绍辉
2023-03-14

这是一个众所周知的缺点。GoF提到Decorator模式的以下责任。

很多小东西。使用装饰器的设计通常会导致由许多看起来相似的小对象组成的系统。这些对象的不同之处在于它们相互连接的方式,而不在于它们的类或变量的值。虽然这些系统很容易被理解它们的人定制,但它们可能很难学习和调试。

 类似资料:
  • Python 拥有一件非常有趣的特性,那就是函数装饰器。这个特性允许您使用一些 非常简介的语法编辑 Web 应用。因为 Flask 中的每个视图都是一个函数装饰器, 这些装饰器被用来将附加的功能注入到一个或者多个函数中。 route() 装饰器您可能已经使用过了。但是在一些情况下您需要实现自己的装饰器。例如, 您有一个仅供登陆后的用户访问的视图,如果未登录的用户试图访问,则把用户 转接到登陆界面。

  • Django为视图提供了数个装饰器,用以支持相关的HTTP服务。 允许的HTTP 方法 django.views.decorators.http 包里的装饰器可以基于请求的方法来限制对视图的访问。若条件不满足会返回 django.http.HttpResponseNotAllowed。 require_http_methods(request_method_list)[source] 限制视图只能

  • 装饰器(Decorators)(被babel支持, 在 03/17 之后作为stage-2的proposal被引入) 如果你在使用类似于mobx的库, 你能够使用装饰器装饰你的函数. 装饰器本质上其实就是将组件传入一个函数. 使用装饰器能让组件更灵活,更可读并且更易修改组件的功能. 不使用装饰器的例子 class ProfileContainer extends Component { //

  • 上一篇文章将通过解决一个需求问题来了解了闭包,本文也将一样,通过慢慢演变一个需求,一步一步来了解 Python 装饰器。 首先有这么一个输出员工打卡信息的函数: def punch(): print('昵称:两点水 部门:做鸭事业部 上班打卡成功') punch() 输出的结果如下: 昵称:两点水 部门:做鸭事业部 上班打卡成功 然后,产品反馈,不行啊,怎么上班打卡没有具体的日

  • fabfile 中可以方便使用的装饰器。 fabric.decorators.hosts(*host_list) 该装饰器用于指定被装饰的函数执行在那台主机或哪些主机列表上。 例如:如果不在控制台覆盖相关参数的话,将会在 host1、host2 以及 host3 上执行 my_func,并且在 host1 和 host3 上都指定了登录用户。 @hosts('user1@host1', 'host

  • 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函数对象有一个__name__属性,可以拿到函数的名字: >>> now.__name__ 'now' >>> f.__name__ 'now' 现在,假设我