Has anyone used the Decorator pattern to draw?

I have an object that will draw itself.

I want to be able to put an unknown number (less than 10) of strings, lines... on the object.  I was thinking I could use the decorator pattern to accomplish this.  I could create an interface with a Draw(Graphics g) or a Draw(object o, Graphics g) for the pattern, and wrapping each string in its own decorator object.  Each instance of the object will have a different set of strings, so I am not printing the same text on each object.

Has anyone tried this   Any experience or advice you might share

Thanks,

Bob



Answer this question

Has anyone used the Decorator pattern to draw?

  • Daniel at SCANA

    Thanks Greg,

    I see your point and I think I can reorganize my objects so that order does not matter. Thanks for the help.

    Bob


  • SeanDr_MS

    This is a very well known use of the decorator pattern.

    The trade off does exist dealing with performance vs maintainability (namely the method indirection, but it is fairly minimal providing this is a rarely called method)

    As fo your example: its applicability to the decorator pattern depends upon how you are viewing the present.

    if I am viewing it such as this (excuse the crappy ascii graphics) (b=bow)

    __b___

    | |

    -----------

    then the decorator pattern is ok providing we never place ribbons around the bow that would cover the side we are viewing i.e.

    __b___

    | r |

    ----r-------

    It is not applicable if we are drawing the box such as ... (r's are ribbon)

    ___r__

    rrrrrBrrrr

    -----r------

    The reason for this is in order to decorate our box in either of the last two cases we have to decorate in specific orders. That is; in building our decorations; we need to know the logic of the orderring of the decorations. A main goal of our decorations should be obliviousness to each other; a bow decoration should not act differently depending on whether or not there is a ribbon decoration also added. If we keep this principle we are forced to apply the ribbon decoration before the bow decoration (otherwise the ribbon would over write the box and our present would look silly) but after the gift wrapping decoration (otherwise the ribbon would be hidden by the wrapping paper). The knowledge required to build the decoration in the proper order would couple the series of decorations; hence renderring all of their power useless.

    Hope this helps you out a bit.

    Greg


  • Satheesh Kumar

    Maybe strings were not the right word.  I do want to decorate, and decorate maybe as deep as 10 objects, each with their own custom decorations.

    A sample might be like wrapping a present.  You start with a container like a box or a bag or a cylinder.  Then you might pick a different wrapping paper from the 5 possible choices, then you may or may not want a bow (maybe two bows), maybe a ribbon, you need a tag that says who the present is from.  Later some newfangled present option will come into the mix (say spray paint with glitter).

    What I want to end up with is an object that has nested all the different features of my present, but I want to call

    IPresent.Draw(Graphics g)

    to draw it without my knowing what all the nested objects are.

    My other concern is will I have performance problems if I hang 5-10 GDI operations nested in say 50 objects.

    BTW, thanks for the reply Greg!

    Bob


  • c0dem0nkey1519

    I would not recommend it because it breaks one of the primary goals of the pattern,obliviousness. Even if you know the orderring knowledge; this code can be come extremely complex and couples items together.

     

    In the example above; it is pretty simple .. there are only 4 levels.

    1) Container
    2) Paper
    3) (Optional) Ribbon
    4) (Optional) Bow

    As you get more items (and more complex orderrings) you would be putting alot of knowledge into the factory generating the objects. This to a large degree defeats the purpose of the decorator because you can't just add a decorator; a change adding a decorator would also require a change to the factory that controlled the orderrings of the decorators.

    Cheers,

    Greg


  • Myyrddraal

    Greg Young wrote:

    The reason for this is in order to decorate our box in either of the last two cases we have to decorate in specific orders.

    I am using a factory to build the object and I will know the order to draw the object.

    I am also thinking that I could alway draw the most inside object first by like this:

    Class Box : IPresent {

    IPresent innerPresent; // embedded Decorator object

    ......

    Public Draw(Graphics g) {

    if (innerPresent != null) {

    innerPresent.Draw(g); // draw any lower level objects first

    // My drawing code here

    }

    }

    I am thinking that I can control the drawing order of the object so that it does draw in the right sequence in the factory that creates them. Would you recommend against that If so, why

    Thanks again,

    Bob


  • marclerman

    The decorator pattern is usually taught using drawing as an example so I am sure many people have done it :)

     

    the particular case I see all of the time is drawing an object ...

      -------------------------
      |                              |
      -------------------------

    then applying a decorator to put a border on this object

    -----------------------------
    |  ------------------------- |
    |  |                              | |
    |  ------------------------- |
    ----------------------------

    The key being that the decorator did not change anything about the original object, it only extended it. This brings me to a worry if I am understanding you correctly  in particular; it seems you are actually drawing the string in the object, thus every object would need to decorate strings which doesn't really make sense ... am I missing something

     

    Note that drawing on top of an object could be considerred a non-destructive decoration, I just need a bit more context.

    Greg


  • Has anyone used the Decorator pattern to draw?