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)