6

The Decorator pattern is usually used to extend the functionality of an object by extending one of it's current methods.

To illustrate, please consider an object object and a decorator decorator. object has one method called methodA(). decorator, because we're in the Decorator pattern, also has this method by inheritance (both object and decorator eventually inherit from the same super-class which has methodA(). Let's call it AbstractObject).

methodA() in object looks like this:

public void methodA(){
    // do stuff
}

methodA() in decorator looks like this:

public void methodA(){
    // do some extra stuff.
    wrappedObject.methodA(); // and then delegate to the wrapped object.
}

It would be used like this:

AbstractObject object = new ConcreteObject();
object.methodA(); // does stuff
object = new ConcreteDecorator(object);
object.methodA(); // does stuff and some more stuff. the extended methodA().

The point of decorator is to extend the functionality of object, and it does this by extending one of object's current methods. So far, classic Decorator.

Now, my question:

As I said Decorator usually extends an object's functionality by adding content to one of the object's current methods.

But what if I wanted to use Decorator to add public methods to an object?

Please consider the following scenario where decorator has another method methodB():

AbstractObject object = new ConcreteObject();
object.methodA(); // does stuff
object = new ConcreteDecorator(object);
((ConcreteDecorator)object).methodB();
// methodB() belongs to ConcreteDecorator() but not to AbstractObject().

As you see if I wanted to do this, I would have to cast object to ConcreteDecorator.

This exposes the concrete type of object and the fact that it's decorated, and as such somewhat defeats the intent of the Decorator pattern. Also, the code invoking methodB() would have to know object is decorated. Again, not very much in the spirit of Decorator.

In light of this I have two questions:

  • Is the Decorator pattern ever used this way? Is it ever used to add public methods to an object, as opposed to only 'extending' it's current methods?

  • Are there situations where this would be a good idea or a wise use of Decorator?

7

The decorator pattern is typically used to avoid an explosion of subclasses. A common example involves ui windows that you may want to have any combination of n attributes (scrollbar, titlebar, resizable, movable, etc.). Supporting all combinations of those n attributes would involve making 2^n subclasses. The decorator pattern prevents the explosion by wrapping around the base window class' existing public methods. The decorator pattern ideally would only require n classes in this case.

For the case you have described, you are adding new public methods; therefore, the decorator pattern probably is not ideal. I cannot think of any situations where it would be ideal to add new methods via a decorator.

A few alternatives to consider:

Subtyping

It is valid to use subtyping to add methods, provided you are keeping the SOLID principles in mind. Therefore, you might consider extending the concrete object to support methodB and then design the decorator around it.

AbstractObject object = new ExtendedConcreteObject();
object.methodA(); // does stuff
object = new ConcreteDecorator(object);
(ConcreteDecorator)object.methodB();
// methodB() belongs to ExtendedConcreteObject() but not to AbstractObject()

Adapter Pattern

Another way to view the problem: by adding a public method, you are changing the object's interface. This can be done by using the adapter pattern. To keep the concrete decorator simple, you might consider creating a decorator and then building an adapter for that decorator.

AbstractObject object = new ConcreteObject();
object.methodA(); // does stuff
object = new ConcreteDecorator(object);
object = new ConcreteAdapter(object);
(ConcreteAdapter)object.methodB();
// methodB() belongs to ConcreteAdapter() but not to AbstractObject() or ConcreteDecorator().
0

Decoration is about adding subtle behavioural changes to an underlying class.

I think your intention is to actually Extend a class. Think "Separation of Concerns". Also, the "Open/Closed" principle springs to mind (which I personally don't entirely agree with)

The point of decoration is that you pass an object around which supports a given interface. If you're doing extra stuff in extra methods, then your application will need to "down-cast" that object to get the extra behavior.

Downcasting to some engineers seems okay, while other engineers feel this isn't a clean solution as code is littered with instanceof keywords. This ties classes to your extended implemetation which requires more diligence when refactoring.

Personally, downcasting of objects should be used sparingly, and should be hidden as much as possible from consuming classes, as it breaks an interface.

All I am saying is it really is a subjective question. Be careful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.