2013-04-14 41 views
0

因此,修饰器模式允许您动态地将行为添加到类中,对吗?但是,装饰器必须从获得行为的类的基类继承,或者必须实现它的一个接口。事实上,我记得的所有例子都有一个暴露的函数,所以应用装饰器效果很好,但是如果你想让装饰器添加行为,比如记录到不具有相同接口的各种类 - 它将不起作用。我在这里错过了什么吗?这是暗示所有我想登录的类应该被包装在同一个接口中,就像命令或其他东西一样?修饰器模式的正确应用

例如

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

class B 
{ 
    bananas(); 
} 

我不能让一个装饰来记录这些类的函数的调用,因为它们是不同的。

回答

2

我相信你可能会误解装饰模式,并且从你对问题的解释中,似乎你实际上还需要别的东西:你需要实现一个横切关注点 - 一些常用的功能可以跨越完全不相关的行为。例如。你想包装无关的函数。

这就是所谓的aspect oriented programming,简称AOP。

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

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

+0

谢谢,但在那个例子中,装饰器仍然需要实现一个特定的方法吗?在考虑你的例子之后,可能有一种方法可以使用反射来制作装饰器(你可以使用反射来做任何事情),而不必实现特定的方法,但是看起来很不雅观并且反设计模式化... – Ford

+1

装饰器模式是一个明确定义的概念:通过包装对象来增强功能,同时向客户端提供相同的接口:http://stackoverflow.com/questions/12379848/decorator-design-pattern-vs-inheritance/12379948#12379948。你所描述的不是装饰者模式(这并不能减少它的价值)。通过拦截示例,您不需要重新实现该方法。您实现了一个方法,然后将其应用于标记了该属性的所有其他方法。请检查代码示例。 –

+0

在这个例子中,拦截器必须实现IService或者它不起作用......但我想我得到了这个想法 - 在实际的IoC框架中,它会使用反射技巧来将拦截器应用于任何具有自定义属性的方法,根本不涉及多态。 – Ford

1

只有必要的装修能够“模仿”的基类是这样的:

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

,并在其构造函数接受基类的一个实例。

+0

对,但如果我有一个行为,我想添加到两个不同的类,我必须做两种类型的装饰器不是吗?如果是这样的话,看起来我最终可以编写大量的代码,因为我当然可以找到一种更简单的方法来将行为包含在某种程度的可重用性中。 – Ford

+0

如果重构旧的类是一个选项,那就把它;总体代码熵的降低在这样的重新设计中几乎是值得的。但是,如果您没有重新选择旧类的选项,则需要尽可能地做到这一点。 –

+0

你是什么意思?这些类只有不同的接口,我如何重构它们才能使其工作? – Ford