locked
Syntactic sugar or short trick for decorator pattern? RRS feed

  • General discussion

  • The decorator pattern and the general principle of favouring composition over inheritance as well as adapters, and probably a few more patterns, involve wrapping an instance of a class that implements an interface inside another wrapper class implementing that same interface by simply calling the inner instance, with a few modifications.

    Edit: I realise that while adapters follow a similar pattern, they tend to have references to concrete classes that don't technically implement the interface, although they may have all the methods required. Whether this idea should generate 'auto-wrappers' for those is another question, right now I'd be happy with the less controversial case for decorators where the implementing inner instance is the same interface.

    Being as this is such a common task, especially when unit testing, it would be nice if there was a simple shorthand for this along the lines of:

    public class wrapper : IInterface
    {
      inner IInterface _implementor;
    }

    where the compiler automatically passes calls to any interface methods that aren't explicitly implemented to the 'inner' instance. This new 'inner' keyword may even elevate composition to the same level of thought as inheritance in the minds of those new to OOP. Although maybe a different word would be less confusing for those coming from Java.

    This would be especially useful when the interface has a large number of methods and you don't happen to have a tool like Resharper.

    Now, given that C# doesn't (yet?) have this keyword, is there some other trick with extension methods or perhaps delegates or lambda functions that can cut down on the need to write implementions for every interface method while still allowing you to make exceptions to the usual delegate to child path?
    Wednesday, August 26, 2009 7:22 AM

All replies

  • There aren't any tricks to do this directly.

    However, this would be possible to implement via an AOP framework, such as PostSharp .  A custom aspect could delegate all of the routines to a member via an attribute.
    Reed Copsey, Jr. - http://reedcopsey.com
    Wednesday, August 26, 2009 5:37 PM
    Moderator
  • I had a quick look at PostSharp and although it adds the additional idea of using attributes I can't see any way around needing to write an implemention for every interface method to please the compiler. Once you've gone to all that effort a policy injection approach won't save you much else or am I missing a trick?

    Your answer does strengthen the argument for a keyword though (maybe 'implementing' would be a better word). It would definitely get my vote for a new language feature. Even Resharper doesn't help if the interface definition changes and you have to go through all your decorating classes again. All that redundant pass-through code also obscures what is usually a simple operation to change a single behaviour.

    Edit: Behaviour changes made me think of one idea that might work. That is the use of a mock library as some of them have clever ways to inject a single behaviourial change. Not sure how but it's the nearest thing that came to mind. Serious overkill mind you. :)
    Thursday, August 27, 2009 2:45 AM
  • Taking this a step further let's make it generic. What I'd like to get is not just a set of decorators that I don't have to go through and modify if an interface changes but preferably a generic decorator that works across interfaces. Here's the idea:

    Let's say I want to modify the behavior of the ToString() method. For now I'll avoid the auto-wrapper idea and create an interface for it:

    public interface IToString
    {
     string ToString();
    }

    So I create a decorator class that, say, adds a new line after every ToString():

    public class NewLineDecorator : IToString
    {
     private IToString _object;
     public NewLineDecorator(IToString o)
     {
      _object = o;
     }

     public string ToString()
     {
       return o.ToString() + "\r\n";
     }
    }

    Now say I've got a group of classes I want to apply this to that do something else too. Let's give them an interface:

    public interface IFoo : IToString
    {
     void Foo();
    }

    Now, in particular context, I'd like to wrap all IFoo objects inside the NewLineDecorator but still reference them as IFoos. I'd also like to do the same for another interface too, IBar.

    Let's say I have some method that  wraps them in a factory somewhere. Instead of having functionally identical, but textually very different, copies of the NewLineDecorator class for both Foo and Bar and any other descendent of IToString, what I'd like to do is:

    public IFoo Decorate(IFoo foo)
    {
     return new NewLineDecorator<IFoo>(foo);
    }

    So the generic NewLineDecorator class would look something like

    public class NewLineDecorator<T> : T where T : IToString  // (and T is still an interface, unless we go for the whole auto-wrapper approach.* )
    {
     private implementing T _object;
     public NewLineDecorator(T o)
     {
      _object = o;
     }

     public string ToString()
     {
       return o.ToString() + "\r\n";
     }
    }

    I hope this shows how this idea is not just about saving a bit (or maybe a lot) of typing. It could be quite powerful for something that wouldn't be too hard to implement. Anyone got anything against the idea?

    *The need to constrain a generic type parameter to being an interface is another topic.

    Edit: Looking at that generic class again I can see it would get confusing if T weren't an interface and you start muddling inheritance and composition and ToString starts getting called on the constructor parameter where any other methods would be called on the decorator itself through inheritance. Not good. Maybe it needs a less confusing syntax.
    Friday, August 28, 2009 12:20 AM
  • My advice is to tackle this at the design level.  Avoid having lots of methods in your interfaces, or change your callers so that they can take advantage of the fact that A has a IFoo, rather than A is a IFoo.
    Friday, August 28, 2009 8:57 PM
  • What the OP is proposing is very much like the mixin pattern, or how templates are used in C++.

    https://blogs.msdn.com/abhinaba/archive/2006/01/06/510034.aspx

    It is the path to the dark side, multiple inheritance.

    http://blogs.msdn.com/csharpfaq/archive/2004/03/07/85562.aspx



    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, August 28, 2009 10:36 PM
    Moderator
  • I've come back to this after finding another post about the same thing. He just didn't spot that it was the decorator pattern he was talking about.

    http://damieng.com/blog/2007/08/06/multiple-inheritance-composition-and-single-responsibility-principle-in-net

    While it may look like Mixins or multiple inheritance, having many of the advantages of such. It is nothing more than what I originally said which is purely syntactic sugar that avoids what must be one of the most common remaining patterns of boilerplate coding that devs still have to write.



    Wednesday, October 14, 2009 7:48 AM
  • The keyword, ' inner ', that you are suggesting is not a variation of the Decorator Pattern.
    It is the path to multiple inheritance of classes, not interfaces.

    Let's suppose that there was such a keyword as you propose.
    Let's take a look at your initial example.


    public class wrapper : IInterface
    {
      inner IInterface _implementor;
    }

    So where does the actual coding for the 'implementor' object come from? 

    If IInterface were an class, then you are talking about basic inheritance.
    If IInterface were an interface, then implementation must come from somewhere.  Where?

    You are also proposing the addition of class members through this other keyword, 'implementing'.
    What is there to stop the use of multiple statements with either keyword?  Nothing, because it is multiple inheritance.
    Sorry, and I know you spin it differently, but that is almost exactly what the mixin pattern is in C++.

    Mark the best replies as answers. "Fooling computers since 1971."
    Wednesday, October 14, 2009 5:14 PM
    Moderator
  • If you allow the IInterface to be a class, yes, that starts to get into the realms of multiple inheritance. That's why I mentioned that 'auto-wrapper' as being a debatable option. You're also right in that the implementation must come from somewhere. You need to set the inner _implementor to a concrete instance, otherwise it will simply throw a null reference exception. How you inject that will be however you'd inject any other instance member. You may even change it at runtime to suddenly switch behaviours. It's composition, not inheritance.

    I see what you mean about multiple inheritance if you allow more than one use of this. If if there is 2 interfaces that are implicitely implemented using this method and they both have the same method then which inner instance gets called? There is an ambiguity there. Is that what you are thinking when you see this as a mixin?

    That ambiguity can be solved by either enforcing a rule of only one implicit interface or by forcing the class to explicitely implement any ambiguous methods. That would be little work for the compiler.

    public class wrapper : IInterface1, IInterface2
    {
    inner IInterface1 _i1;
    inner IInterface2 _i2;
    
    public object CommonMethod()
    {
     return i1.CommonMethod();
    }
    }
    

    Anyway. I can see that there needs to be lines drawn around this idea.

    The reason I came back to this is that I was looking in Dynamic Proxy after it caused problems with debugging mocks (a known bug ) and it noticed that it does just what we are talking about here, that is an implicitly forwarding decorator, that allows you to override the default behaviour of a method. Only it is through interceptors which bypasses the need for an interface altogether.

    In future if I need to create a set of common decorators as in my second post I'll look into using Dynamic Proxy.
    Wednesday, October 14, 2009 11:41 PM
  • A rule of only one implicit interface already exists in C#.  It is called simple inheritance.
    Mark the best replies as answers. "Fooling computers since 1971."
    Thursday, October 15, 2009 12:41 AM
    Moderator