Skip to main content

Use Cases For The Decorator Pattern

Let's explore some real-world scenarios where the Decorator pattern could be a good fit

Graphic User Interfaces (GUIs)

GUI toolkits often make use of the Decorator pattern. For instance, a window in a GUI could be decorated with borders, scrollbars, or other graphical elements. Each decorator would add its own functionality without modifying the window's core behavior. This makes the design more flexible and allows for dynamic customization of the GUI.

In this class diagram:

  • Window <|.. BaseWindow : implements and Window <|.. WindowDecorator : implements denote that both BaseWindow and WindowDecorator implement the Window interface.
  • WindowDecorator <|-- BorderDecorator : extends, WindowDecorator <|-- ScrollbarDecorator : extends and WindowDecorator <|-- TitleBarDecorator : extends show that BorderDecorator, ScrollbarDecorator, and TitleBarDecorator extend the WindowDecorator.
  • WindowDecorator o-- Window : - has a represents that WindowDecorator has a reference to a Window object (composition).
  • The class Window, class BaseWindow, class WindowDecorator, class BorderDecorator, class ScrollbarDecorator, and class TitleBarDecorator blocks define the classes and interfaces with their methods. The <<interface>> tag indicates that Window is an interface.
  • The + and - before the method and attribute names represent public and private access modifiers, respectively.

Middleware in Web Frameworks

The Decorator pattern is often used in web development frameworks to provide middleware services. Middleware functions are functions that have access to the request and response objects, and the next middleware function in the application's request-response cycle. They can be used to perform actions like authentication, logging, error handling, etc. For instance, in Express.js (a popular Node.js framework), middleware functions can be thought of as decorators that add functionality to the HTTP request/response process.

Below is an abstracted class diagram demonstrating the Decorator pattern in the context of a web framework, where we have a RequestHandler that can be decorated with different middleware like AuthenticationMiddleware, LoggingMiddleware, or ErrorHandlingMiddleware:

In this class diagram:

  • RequestHandler <|.. BaseRequestHandler : implements and RequestHandler <|.. MiddlewareDecorator : implements denote that both BaseRequestHandler and MiddlewareDecorator implement the RequestHandler interface.
  • MiddlewareDecorator <|-- AuthenticationMiddleware : extends, MiddlewareDecorator <|-- LoggingMiddleware : extends, and MiddlewareDecorator <|-- ErrorHandlingMiddleware : extends show that AuthenticationMiddleware, LoggingMiddleware, and ErrorHandlingMiddleware extend the MiddlewareDecorator.
  • MiddlewareDecorator o-- RequestHandler : - has a represents that MiddlewareDecorator has a reference to a RequestHandler object ( composition).
  • The class RequestHandler, class BaseRequestHandler, class MiddlewareDecorator, class AuthenticationMiddleware, class LoggingMiddleware, and class ErrorHandlingMiddleware blocks define the classes and interfaces with their methods. The <<interface>> tag indicates that RequestHandler is an interface.
  • The + and - before the method and attribute names represent public and private access modifiers, respectively.

Access Control or User Permissions

You can use decorators to control access permissions for a user. For example, you might have a User object, and you want to add different levels of access control such as AdminUser, ReadOnlyUser, etc. Instead of modifying the User class directly or using inheritance which could become unwieldy with many types of users, you can use decorators to dynamically assign and remove these permissions.

Here is a class diagram demonstrating the Decorator pattern for a User object that can be decorated with different permissions like AdminPermissions, ReadPermissions, or WritePermissions:

In this class diagram:

  • User <|.. BasicUser : implements and User <|.. PermissionDecorator : implements denote that both BasicUser and PermissionDecorator implement the User interface.
  • PermissionDecorator <|-- AdminPermissionDecorator : extends, PermissionDecorator <|-- ReadPermissionDecorator : extends, and PermissionDecorator <|-- WritePermissionDecorator : extends show that AdminPermissionDecorator, ReadPermissionDecorator, and WritePermissionDecorator extend the PermissionDecorator.
  • PermissionDecorator o-- User : - has a represents that PermissionDecorator has a reference to a User object (composition).
  • The class User, class BasicUser, class PermissionDecorator, class AdminPermissionDecorator, class ReadPermissionDecorator, and class WritePermissionDecorator blocks define the classes and interfaces with their methods. The <<interface>> tag indicates that User is an interface.
  • The + and - before the method and attribute names represent public and private access modifiers, respectively.

Each of these scenarios involves situations where you want to add functionality to objects dynamically and transparently, without affecting other objects. Decorators offer a flexible and maintainable way to do this.

TypeScript Course Instructor Image
TypeScript Course Instructor Image

Time To Transition From JavaScript To TypeScript

Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.

SEE COURSE DETAILS

What Can You Do Next 🙏😊

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for software developers.

YouTube @cloudaffle