I've implemented a Decorator Pattern in order to decorate the generated controls that are created using a Factory class. You can check my previous post on how I implemented a Factory Pattern in JavaScript.
I'm integrating a decorator pattern into the existing DomFactory class for enhancing the styles of the controls, by creating a separate decorator function or class that modifies the elements created by the factory class. By definition, the decorator pattern is a structural design pattern that allows behavior to be added to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class.
function DomFactory() { // ... existing methods ... // Enhance the style of a control element this.enhanceStyle = (element, styleProps) => { for (const [key, value] of Object.entries(styleProps)) { element.style[key] = value; } } } // Decorator function to apply custom styles function styleDecorator(control, styleProps) { control.enhanceStyle(control.checkbox, styleProps.checkbox); control.enhanceStyle(control.labelElement, styleProps.label); } // Usage const factory = new DomFactory(); const control = factory.createCheckbox('example', { label: 'Example' }, true); // Define custom styles const customStyles = { checkbox: { margin: '10px', // Other CSS properties }, label: { color: 'blue', // Other CSS properties } }; // Apply styles using the decorator styleDecorator(control, customStyles);
As mentioned in the previous post, using a decorator along with a factory helps to follow 3 out of the 5 SOLID design principles:
- by decoupling the code to instantiate classes from the code to add details/styles(decorate) we make sure each class has a single responsibility, or a single reason to change. This is called single responsibility principle. You can also consider a way of decouple presentation from data structure.
- Open-closed principle allows us to add new styles without changing the main code for creating objects.
- not directly but it allows easier extending functionality by being able to inject new styles by adding new decorator classes. By using the dependency inversion principle we can rely on a form of an abstract decorator and based on the context we can pass different concrete decorators.
Top comments (0)