开发者

How do you implement the Decorator pattern if you can't inherit from the class you want to decorate?

This is more a design question... You can't do a decorate design pattern if:

1) The object is marked "sealed" meaning you can't extend from it. 2) or you want to override a method but its not virtual.

What ca开发者_StackOverflow社区n you do then? Taken that you can't change the class source code if you don't have the source code (like a 3rd party library).


Inheritance isn't necessary for a Decorator pattern. The simplest case is if the object you want to decorate implements an interface. Then your decorator can simply implement the same interface:

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

Now you can just do:

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

The specifics of what are possible will depend on the exact nature of the class you're trying to decorate.


Lots of approaches you could take depending on how much control over the code you really have:

1) Are you passing an instance of a sealed class to third-party code? If so, there's no much you can do, except pray that your third-party accepts an interface instead of a concrete object.

Its wholly possible to write hooks into the CLR to intercept methods in your sealed class, which is how some mocking frameworks work to mock out non-virtual methods and sealed classes. I don't recommend this because your third-party code was written against a particular implementation of an object, and swapping out the implementation under the third-party code's nose could have non-trivial, undefined consequences.

2) Are you consuming the sealed class in your own code? If so, then go go gadget wrapper! Create a non-sealed class with the same public methods as your sealed class, the public methods should pass through to your sealed object, then you can override your class's functionality as needed.

3) Do you own the code to the sealed class? If so, find the class definition, double-click the 'sealed' keyword to highlight it, hit the delete key as needed ;) Or maybe swap out the methods which accept your sealed object for an interface with the same public methods instead.


You can create your own class that wraps the 3rd party class and decorate that class. Your class will use the wrapped class implementation. The wrapper class acts as an Adapter.


If you can't inherit and the original class doesn't implement any interfaces that you can also implement on your decorator, then I believe you should try a proxy class or an adapter. And if that's not possible too, well, you always have an "alternative technical resource": you could define an conversion operator allowing to cast your decorator to the original one (altough I believe that this is not a very good option).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜