Question

Maybe I'm missing something here, and I admit my OO skills are not what I'd like them to be, but looking at this example of the decorator pattern, I notice that the UML declares that a decorator is both is-a component and has-a component. This puzzles me a little bit in that it seems redundant for it to be both, and, in fact, when I test the "real world" code, found here, and modify the decorator class to look like this:

abstract class Decorator /*: LibraryItem*/ {
    protected LibraryItem libraryItem;

    // Constructor
    public Decorator(LibraryItem libraryItem) {
        this.libraryItem = libraryItem;
     }

     public /* override */ void Display() {
         libraryItem.Display();
     }
}

...

class Borrowable : Decorator {
    protected List<string> borrowers = new List<string>();

    // Constructor
    public Borrowable(LibraryItem libraryItem) : base(libraryItem) { }

    public void BorrowItem(string name) {
        borrowers.Add(name);
        libraryItem.NumCopies--;
    }

    public void ReturnItem(string name) {
        borrowers.Remove(name);
        libraryItem.NumCopies++;
    }

    public new /*override*/ void Display() {
        base.Display();

        foreach (string borrower in borrowers) {
            Console.WriteLine(" borrower: " + borrower);
        }
    }
}

What I've done here is simply removed the is-a relationship by commenting out the ": LibraryItem" but kept the has-a relationship by keeping "protected LibraryItem libraryItem;". I also commented out the override on the Display methods replacing one with the new keyword. As best I can tell, this works just as well as the original code.

Am I missing something here? Is it really necessary for the decorator to inherit from component? The UML diagram and implemented code would certainly suggest so, but I'm curious if there's something I'm not seeing or addressing properly.

Thoughts?

Was it helpful?

Solution

The decorator pattern is suppose to

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. This pattern is designed so that multiple decorators can be stacked on top of each other, each time adding a new functionality to the overridden method(s).

In effect you can if your decorator classes inherits from the same type that it is decorating one could chain more and more decorators thus adding more and more responsibility while still being able to use it where the original base class was called.

You would for example not be able to pass Borrowable where you required a LibraryItem in your example. Your example is just a composition example and not a decorator example.

Look at C# Stream and its decorators.

Lets for example say I had a Document class. Now I could have a DocumentWithSpellCheckingDecorator and DocumentWithGrammarCheckingDecorator. I could use both decorators or just one or the other, but still I would have a Document and can be used as a Document since I just decorated it with more functionality. Maybe this is not the perfect example, but hope it helps.

Btw the dofactor website is easy to understand but sometimes does not quite get the message across. I have found this on other patterns on the site as well.

OTHER TIPS

The decorated component IS-A component, for example a BorderedImage is an image decorated with a border, and it can be used in any place that it's Image superclass would be used.

This means BorderedImage can be passed to any code that uses an Image, for example a method that calls saveImage(Image image).

Breaking the inheritance relation between BorderedImage and Image would prevent the use of the decorated image in code that takes an Image.

This would mean that a BorderedImage would no longer simply be an Image. Keeping the inheritance relation is therefore essential to keep the meaning intended by the the Decorator pattern.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top