Introduction
Attach additional responsibilities to an object dynamically. Decorators provide
a flexible alternative to subclassing for extending functionality.
Participants:
Component
- Defines the interface for objects that can have responsibilities added
to them dynamically.
- This participant cannot be read-only.
Concrete component
- Defines an object to which additional responsibilities can be attached.
- This participant cannot be read-only.
Decorator
- Maintains a reference to a Component object and defines an interface that
conforms to the Component's interface.
- This participant cannot be read-only.
- This participant cannot be an interface.
In the Attribute field you can specify the name of a Decorator's attribute where it keeps a reference
to a Component object.
The Initialization variant option defines the kind of initialization of that attribute.
Concrete decorator
- Adds responsibilities to the component.
- This participant cannot be read-only.
- This participant cannot be an interface.
If Copy documentation is checked, it copies Javadoc comments from methods in interfaces
participating in the pattern to the stubs of these methods that the pattern created in classes implementing
such interfaces.
If Create pattern links is checked, it generates additional links that can be used by this
pattern later to determine classes and interfaces participating in the pattern.
This means that if you check this option and use the pattern to create a set of classes and interfaces,
the pattern invoked for some participant later (using the Choose Pattern command on the right-click menu) will
automatically find all other participants (if possible) and fill in participant fields
with their names.
Furthermore, if you apply the pattern with this option checked and later invoke the pattern
using the Choose Pattern command on the right-click menu for some participant, the pattern
has an additional field called Use selected class as, containing possible roles for the selected
element.
This option is very useful when you are planning to change something in the classes/interfaces
participating in the pattern. For example, if this option is on and after creating the classes and
interfaces you
add several methods to a certain interface-participant (and this change must be reflected somehow in other
participants), all you need to do is select this
changed interface,
invoke the Choose Pattern dialog for this element and select the original pattern. After that
the pattern determines other participants and you only need to click Finish.
The pattern will modify all other classes and interfaces according to your changes.
Applicability
Use the Decorator pattern
- To add responsibilities to individual objects dynamically and transparently, that is, without
affecting other objects.
- For responsibilities that can be withdrawn.
- When extension by subclassing is impractical. Sometimes a large number of independent extensions
are possible and would produce an explosion of subclasses to support every combination. Or a class
definition might be hidden or otherwise unavailable for subclassing.
Documentation of OCL-Schemata
- Method Specifications are copied from the Component to Decorator and Concrete Decorators if the box Copy Specs from Methods is tagged.
- Option Simply Decorated:
- An association innerDecorators from Decorator to itself is created with multiplicity 0..*
- The set represented by the association is defined to contain the transitive closure of the components:
context Decorator
inv: if (not (self.component.oclIsKindOf(Decorator)))
then (allInnerDecorators->isEmpty)
else (allInnerDecorators=self.component.oclAsType(Decorator).allInnerDecorators->
including(self.component.oclAsType(Decorator))) endif
- all elements of the innerDecorators set are of a concrete decorator class that is unique in the set:
inv: self.allInnerDecorators->forAll(cd | not(cd.oclIsKindOf(ConcreteDecorator)))
- Optional tags Specify Query: If the query is tagged then it is specified: the value of the query in the Decorator is the same as the query on the component:
context Decorator::query(...)
post: result=self.component.query(...)