【问题标题】:The correct application of the decorator pattern装饰器模式的正确应用
【发布时间】:2013-04-14 02:32:02
【问题描述】:

所以装饰器模式允许您动态地向类添加行为,对吗?但是,装饰器必须从获得行为的类的基类继承,或者必须实现其接口之一。事实上,我能回忆起的所有示例都有一个公开的函数,因此应用装饰器效果很好,但是如果你想让装饰器添加行为,例如记录到没有相同接口的各种类 - 它不会工作.我在这里错过了什么吗?这是否暗示我想要记录的所有类都应该包装在同一个接口中,比如命令或其他东西?

例如

class A
{
    whatever();
    idontknow();
}

class B
{
    bananas();
}

我无法制作装饰器来记录这些类中函数的调用,因为它们不同。

【问题讨论】:

    标签: c# design-patterns


    【解决方案1】:

    我相信您可能误解了装饰器模式,并且从您对问题的解释看来,您实际上还需要其他东西:您需要实现横切关注点 - 一些可以完全应用的通用功能无关的行为。例如。您想围绕不相关的功能进行日志记录。

    这称为aspect oriented programming,简称AOP。

    有一些工具可以让你拦截对方法的调用,并用所需的行为来增强它们,即你可以在方法调用周围添加日志记录,或者确保用户有足够的权限来执行调用,等等。 .NET 中的这些工具通过修改 IL 来实现这一点,而其他工具则在运行时动态包装类型。

    我在this answerhere too 中提供了一个示例。

    【讨论】:

    • 谢谢,但在那个例子中,装饰器仍然需要实现一个特定的方法,不是吗?在考虑了您的示例之后,可能有一种方法可以使用反射来制作装饰器(您可以使用反射来做任何事情),它不必实现特定的方法,但看起来非常不雅且反设计模式......
    • 装饰器模式是一个定义明确的概念:通过包装对象来增强功能,同时为客户端提供相同的接口:stackoverflow.com/questions/12379848/…。您所描述的不是装饰器模式(这并没有降低它的价值)。使用拦截示例,您无需重新实现该方法。您实现一种方法,然后将其应用于所有其他标记有该属性的方法。请检查代码示例。
    • 在那个例子中,拦截器必须实现 IService 否则它不起作用......但我想我明白了 - 在实际的 IoC 框架中,它会使用反射技巧将拦截器应用于任何具有自定义属性的方法,根本不涉及多态性。
    • 那是因为该示例使用了一种装饰器形式,如答案中所述,而不是正确的 AOP - 因此是“穷人的 AOP”。按照该答案中的第二个链接进行真正的 AOP 实现,或在 .NET 中搜索 Google AOP。另外,这里有一个例子:stackoverflow.com/questions/15323009/…
    【解决方案2】:

    装饰器只需要像这样“模仿”基类:

    Class ADecorator : A {
      ADecorator(A a) { /* etc */ }
    
      void whatever();
      void idontknow();
    }
    
    class BDecorator1 : B {
      BDecorator1(B b) { /* etc */ }
    
      void bananas();
    }
    
    class BDecorator2 : B {
      BDecorator2(B b) { /* etc */ }
    
      void bananas();
    }
    

    并在其构造函数中接受基类的实例。

    【讨论】:

    • 对,但是如果我有一种行为,我想添加到两个不同的类中,我必须制作两种类型的装饰器,不是吗?如果是这样的话,当我当然可以找到一种更简单的方法来包含具有某种程度的可重用性的行为时,我似乎最终可能会编写大量代码。
    • 如果重构旧类是一种选择,那就接受吧;在这样的重新设计中,总体代码熵的减少几乎肯定是值得的。但是,如果您没有重构旧类的选项,则需要尽力而为。
    • 什么意思?这些类只是具有不同的接口,我如何重构它们以使其工作?
    • 所有它们的非公共属性可以被重构为装饰器,只留下公共属性和任何所需的装饰器支持。
    • 你为什么不做一些功课,并在努力中遇到的具体问题回电。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 2014-10-17
    • 2011-12-15
    • 2013-05-07
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多