Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 装饰图案的正确应用_C#_Design Patterns - Fatal编程技术网

C# 装饰图案的正确应用

C# 装饰图案的正确应用,c#,design-patterns,C#,Design Patterns,所以decorator模式允许您动态地向类添加行为,对吗?但是,装饰器必须从获得行为的类的基类继承,或者必须实现它的一个接口。事实上,我所记得的所有示例都有一个公开的函数,因此应用decorator可以很好地工作。但是,如果您想让decorator添加行为,例如记录到没有相同接口的各种类中,该怎么办?它将不起作用。我是不是遗漏了什么?这是不是暗示我想记录的所有类都应该包装在同一个接口中,比如命令之类的 比如说 class A { whatever(); idontknow();

所以decorator模式允许您动态地向类添加行为,对吗?但是,装饰器必须从获得行为的类的基类继承,或者必须实现它的一个接口。事实上,我所记得的所有示例都有一个公开的函数,因此应用decorator可以很好地工作。但是,如果您想让decorator添加行为,例如记录到没有相同接口的各种类中,该怎么办?它将不起作用。我是不是遗漏了什么?这是不是暗示我想记录的所有类都应该包装在同一个接口中,比如命令之类的

比如说

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

class B
{
    bananas();
}

我无法让decorator记录这些类中函数的调用,因为它们不同。

只需要decorator能够像这样“模拟”基类:

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();
}

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

装饰程序只需要能够像这样“模拟”基类:

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();
}

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

我相信您可能误解了decorator模式,从您对问题的解释来看,看起来您实际上还需要其他东西:您需要实现一个跨领域的关注点——一些可以应用于完全不相关行为的通用功能。例如,您希望围绕不相关的函数进行日志记录

这被称为,简称AOP

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


我在和中提供了一个示例。

我相信您可能误解了decorator模式,并且从您对问题的解释来看,似乎您实际上还需要其他东西:您需要实现一个交叉关注点—一些可以应用于完全不相关行为的常见功能。例如,您希望围绕不相关的函数进行日志记录

这被称为,简称AOP

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


我在和中提供了一个示例。

对,但是如果我有一个行为,我想添加到两个不同的类中,我必须创建两种类型的装饰器,不是吗?如果是这样的话,当我可以找到一种更简单的方法来包含具有一定程度可重用性的行为时,我似乎可以编写大量代码;在这样的重新设计中,总体代码熵的减少几乎肯定是值得的。但是,如果您没有重构旧类的选项,那么您需要在能够重构旧类之前做好准备。您的意思是什么?这些类只是有不同的接口,我如何重构它们使其工作?它们所有的非公共属性都可以重构为decorator,只留下公共属性和任何所需的decorator支持。为什么不做一些家庭作业,然后回电话说明在这项工作中遇到的具体问题。对,但是如果我有一个行为,我想添加到两个不同的类中,我必须生成两种类型的装饰器,不是吗?如果是这样的话,当我可以找到一种更简单的方法来包含具有一定程度可重用性的行为时,我似乎可以编写大量代码;在这样的重新设计中,总体代码熵的减少几乎肯定是值得的。但是,如果您没有重构旧类的选项,那么您需要在能够重构旧类之前做好准备。您的意思是什么?这些类只是有不同的接口,我如何重构它们使其工作?它们的所有非公共属性都可以重构为decorator,只留下公共属性和任何所需的decorator支持。为什么不做一些家庭作业,在这个例子中,装饰者仍然需要实现一个特定的方法,不是吗?在考虑了您的示例之后,可能有一种方法可以使用反射(您可以使用反射做任何事情)来制作装饰器,该方法不必实现特定的方法,但看起来非常不雅观,而且是反设计模式……装饰器模式是一个定义良好的概念:通过包装对象来增强功能,向客户端提供相同接口时:。您所描述的不是decorator模式(这不会降低它的价值)。对于拦截示例,您不需要重新实现该方法。实现一个方法,然后将该方法应用于标记有该属性的所有其他方法。请检查代码示例。在该示例中,拦截器必须实现IService,否则将无法工作。。。但我想我明白了这个想法——在实际的IoC框架中,它会使用反射技巧将拦截器应用于任何具有自定义属性的方法,并且根本不涉及多态性。这是因为该示例使用了一种装饰器形式,如答案中所述,而不是正确的AOP——因此称为“可怜的人的AOP”。按照答案中的第二个链接进行真正的AOP实现,或者.NET中的google AOP。另外,这里还有一个例子:谢谢,但在这个例子中,装饰者仍然必须实现一个特定的方法,不是吗?在考虑您的示例之后,可能有一种方法可以使用反射制作装饰器(您可以使用reflec做任何事情)