The Decorator Pattern is dynamic extension-at-runtime of classes. It dynamically forms a is-a relationship.
I started to wonder if I was over-complicating my API by using the Decorator Pattern after I got this answer about the difference between a mixin and an abstract class.
Using a Decorator to apply MixinsA Decorator is simply a function that receives a class as a parameter. The HasLevel Decorator can now be used to annotate any class, providing the ability to gain a level!
Mixins are an alternative class design pattern that avoids both single-inheritance class fragmentation and multiple-inheritance diamond dependencies. A mixin is a class that defines and implements a single, well-defined feature. Subclasses that inherit from the mixin inherit this feature—and nothing else.
Composite is intended to combine and represent multiple objects as a single one (of the same base type) - i.e. 1 to Many, while Decorator enhances (or adds on top of) the capability of a single object of the same type - i.e. 1 to 1.
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.
A mixin is apt when you're adding some behavior to your class. e.g. the ability to enumerate in case of a collection type. You can mixin as many sets of behavior into your class as you want. Its a nice way to reuse common code ; you basically get a bunch of methods for free.
A decorator on the other hand is more of a sneaky interceptor. It exposes the same public interface as the target object, contains a target object to which it delegates all client calls ; however it decorates the call with some pre and/or post processing. e.g. if I'm writing code against a MyCollection and I want all calls to this type to be logged. I could derive a new decorator MyCollectionWithTimeStampedLogging both deriving from an ICollection base so that they look identical to the client. The decorator would take an instance of ICollection as a ctor param and delegate calls to it. e.g. Add would look like this
public void Add( int item) { _logger.log(String.Format( "{0} Add called with param {1}", DateTime.Now, item.ToString()); _collection.Add(item); _logger.log(String.Format( "{0} Add completed with param {1}", DateTime.Now, item.ToString()); }
When using the decorator pattern, you generally are encapsulating, rather than extending (or mixing in) the base class. Often you do this because you want to use the functionality of the class but you want to wrap the calls to it so you can do some extra steps before or after the call. Consider a LoggerDecorator
public class LoggerDecorator implements SomeInterface { private SomeInterface delegate; public void someMethod() { LOGGER.debug("someMethod called"); delegate.someMethod(); } }
You don't want to actually expose the delegate but you want to use its functionality. So whether or not you use mixins, extends a class, or decorate really depends on what you're trying to do. Are you extending a class and adding new functionality to it? Or are you wrapping/decorating the class?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With