如果你不能从你想要装饰的类继承,你如何实现Decorator模式?

时间:2010-05-08 14:40:34

标签: c#

这更像是一个设计问题......如果出现以下情况,则无法进行装饰设计模式:

1)对象标记为“已密封”,意味着您无法从中扩展。 2)或者你想覆盖一个方法,但它不是虚拟的。

那你能做什么?如果您没有源代码(如第三方库),则无法更改类源代码。

4 个答案:

答案 0 :(得分:5)

Decorator模式不需要继承。最简单的情况是,您要装饰的对象是否实现了接口。然后你的装饰者可以简单地实现相同的界面:

[   IWindow   ]
[ + Draw()    ]
---------------
  |
  +--- [   Window    ]
  |    [ + Draw()    ]
  |
  |
  +--- [ DecoratedWindow ]
       [ + Draw()        ]
       -------------------
         |
         +--- [ BorderDecorator ]
         |
         +--- [ VerticalScrollbarDecorator ]
         |
         +--- [ HorizontalScrollbarDecorator ]

现在你可以这样做:

IWindow w = new BorderDecorator(
             new HorizontalScrollBarDecorator(
              new VerticalScrollBarDecorator(
               new Window(80, 24))));

// This is a window with a border and scrollbars, even though
// the original Window class has no idea what those are.
w.Draw();

可能的具体细节将取决于您尝试装饰的课程的确切性质。

答案 1 :(得分:2)

您可以采取多种方法,具体取决于您对代码的控制程度:

1)您是否将密封类的实例传递给第三方代码?如果是这样,除了祈祷你的第三方接受一个界面而不是一个具体的对象之外,你无能为力。

完全有可能在CLR中编写钩子来拦截密封类中的方法,这就是一些模拟框架如何模拟非虚方法和密封类。我推荐这个,因为您的第三方代码是针对对象的特定实现编写的,并且在第三方代码的鼻子下交换实现可能会产生非平凡的,未定义的后果。

2)您是否在自己的代码中使用密封类?如果是这样,那就去吧小工具包装!使用与密封类相同的公共方法创建一个非密封类,公共方法应该传递给密封对象,然后根据需要覆盖类的功能。

3)你是否拥有密封课程的代码?如果是这样,找到类定义,双击'sealed'关键字以突出显示它,根据需要点击删除键;)或者可以用相同的公共方法替换接受密封对象的接口的方法。< / p>

答案 2 :(得分:1)

您可以创建自己的类来包装第三方类并装饰该类。您的类将使用包装的类实现。包装类充当适配器。

答案 3 :(得分:0)

如果你不能继承并且原始类没有实现你也可以在你的装饰器上实现的任何接口,那么我相信你应该尝试代理类或适配器。如果那也不可能,那么,你总是有一个“替代技术资源”:你可以定义一个conversion operator,允许你的装饰师投射到原来的(尽管我认为这不是一个很好的选择)