Decorator Pattern
The decorator pattern is a structural design pattern
where additional functionality is added to an object of a given class without
altering the behavior of any other instances of that class. This helps reduce
the need for subclassing to add or extend functionality. This also helps the
overall design adhere to the single responsibility principle and keeps the code
DRY (Don’t Repeat Yourself).
Command Pattern
The command pattern is a behavioral pattern where
one object stores the information necessary to perform a certain action. This
provides a layer of decoupling between the object calling the method and the
object performing the action. The command object stores the state and
information necessary to execute a command on a receiver object. The client
class—which is the one starting the sequence that will result in the command
being executed—provides the invoker or director class with a request. The
invoker then executes the command. The command, in turn, calls the pre-defined
function on the receiver class which performs the desired action.
Decorator Pattern Example
The decorator pattern is useful in situations where
you have a base object that has various different options that could be applied
to the base object. The base object provides the core functionality and the
decorators provide additional functionality. Those decorators can be applied
dynamically as needed in the software.
In this paper, we’ll use sugar
cookies as an example. The base sugar cookie class might only concern itself
with the ingredients of the cookie itself as that is the core part of any sugar
cookie. However, a sugar cookie by itself, while tasty, isn’t the sweet treat
we’ve come to love. A good sugar cookie will often be decorated with frosting
and/or sprinkles. To represent this, we’ll then create decorator classes to
represent the frosting option and the sprinkles option. It should be noted that
these decorators are not mutually exclusive. As with most implementations of
the decorator pattern, any number of decorators can be applied so long as they
implement the correct interface.
The decorator pattern is a good choice for
situations like this one. It allows the base class to receive additional
functionality while not being modified itself. This can be done statically or
dynamically at run time. The decorator pattern reduces the complexity of the
code in the base class by extracting the optional functionality out into
separate classes. This makes the code cleaner and easier to extend in the
future. When faced with a situation where there’s some core object with
optional functionality, the decorator pattern is a solid choice.
In this example, the command pattern would be a very
poor choice. One reason for this is that the decorator pattern and the command
pattern are completely different types of patterns. The decorator pattern is a
structural pattern—meaning it’s targeted at class structure—and the command
pattern is a behavioral pattern—meaning it’s targeted at the events or
functionality of the software. In the sugar cookie example, there are no events
or behaviors to be concerned with. Therefore, the command pattern is useless in
this case. If the sugar cookie were to be expanded to model human interactions
with the cookie or other ingredients, then the command pattern could be useful;
however, as the example currently stands, the command pattern is of no use.
Command Pattern Example
While the command pattern was not useful in our
simple sugar cookie example, there are a great number of situations where the
command pattern is very useful. As discussed above, the command pattern is a
behavioral pattern. When dealing with events, the command pattern can be a
great tool to use. Today we’ll discuss its usefulness via an example of
software engineering.
In software engineering, there are
various roles to a successful team. In this example, we’ll use three roles and
one object to illustrate the command pattern. The roles are as follows:
Product Manager: The product manager interfaces with customers,
gathers feature requests, and vets them so the value of each feature request is
known. In this example, this is the client.
Product Owner: The product owner works with the development team
and the product manager to prioritize the work and select work items for a
team. In this example, this is the director or invoker.
Software Engineer: The software engineer implements the feature in
the software. In this example, this is the receiver.
The one object we’ll use in this example is a story. A story is a feature that is
needed in the software. It has enough detail that a software engineer can
implement it. In this example, the story is the command.
The behavior in this
example will proceed as follows:
1. The
product manager submits a story to the team
2. The
product owner tells the team to work on the story
3. When
ready, a software engineer implements the story
In this example, we see that the product manager
doesn’t need to know anything about computer programming to get the story
implemented. The story acts as the command which abstracts the state and
functions needed for a software engineer to implement (aka execute the command)
later. There is no need to share details of any of the actors with each other
as the command class abstracts that away and stores it.
This can greatly simplify some event handling
strategies and simplify the dependencies to execute a given event. Because the
client doesn’t need to know anything about the object that’s executing the
given request, it is not dependent on it. This results in a simpler client
class.
The decorator pattern would be a poor choice in this
case mainly for reasons already discussed. The decorator pattern is a
structural pattern where this example concerns itself more with the behavior of
the software. The decorator pattern would be of no use in managing the stories
of the behaviors of the actors here. If the example were to concern itself with
different types of stories or something similar, then the decorator pattern may
be of some use.
Conclusion
Both the decorator and the command patterns are very
useful when faced with problems they were designed to solve. The decorator
pattern is a structural pattern that can be used to easily add functionality to
base components. The command pattern if a behavioral pattern that is useful
when abstracting the details of an action. The decorator pattern is often used
in GUI components that may need to dynamically change. The command pattern is
often used in distributed computing, event delegation, and parallel processing,
among other things. Both are effective at solving the problems they were
designed to solve.
Comments
Post a Comment