Decorator and Command Design Patterns

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