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
andWindow <|.. WindowDecorator : implements
denote that bothBaseWindow
andWindowDecorator
implement theWindow
interface.WindowDecorator <|-- BorderDecorator : extends
,WindowDecorator <|-- ScrollbarDecorator : extends
andWindowDecorator <|-- TitleBarDecorator : extends
show thatBorderDecorator
,ScrollbarDecorator
, andTitleBarDecorator
extend theWindowDecorator
.WindowDecorator o-- Window : - has a
represents thatWindowDecorator
has a reference to aWindow
object (composition).- The
class Window
,class BaseWindow
,class WindowDecorator
,class BorderDecorator
,class ScrollbarDecorator
, andclass TitleBarDecorator
blocks define the classes and interfaces with their methods. The<<interface>>
tag indicates thatWindow
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
andRequestHandler <|.. MiddlewareDecorator : implements
denote that bothBaseRequestHandler
andMiddlewareDecorator
implement theRequestHandler
interface.MiddlewareDecorator <|-- AuthenticationMiddleware : extends
,MiddlewareDecorator <|-- LoggingMiddleware : extends
, andMiddlewareDecorator <|-- ErrorHandlingMiddleware : extends
show thatAuthenticationMiddleware
,LoggingMiddleware
, andErrorHandlingMiddleware
extend theMiddlewareDecorator
.MiddlewareDecorator o-- RequestHandler : - has a
represents thatMiddlewareDecorator
has a reference to aRequestHandler
object ( composition).- The
class RequestHandler
,class BaseRequestHandler
,class MiddlewareDecorator
,class AuthenticationMiddleware
,class LoggingMiddleware
, andclass ErrorHandlingMiddleware
blocks define the classes and interfaces with their methods. The<<interface>>
tag indicates thatRequestHandler
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
andUser <|.. PermissionDecorator : implements
denote that bothBasicUser
andPermissionDecorator
implement theUser
interface.PermissionDecorator <|-- AdminPermissionDecorator : extends
,PermissionDecorator <|-- ReadPermissionDecorator : extends
, andPermissionDecorator <|-- WritePermissionDecorator : extends
show thatAdminPermissionDecorator
,ReadPermissionDecorator
, andWritePermissionDecorator
extend thePermissionDecorator
.PermissionDecorator o-- User : - has a
represents thatPermissionDecorator
has a reference to aUser
object (composition).- The
class User
,class BasicUser
,class PermissionDecorator
,class AdminPermissionDecorator
,class ReadPermissionDecorator
, andclass WritePermissionDecorator
blocks define the classes and interfaces with their methods. The<<interface>>
tag indicates thatUser
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.
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 DETAILSWhat 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.