The Decorator pattern adds behaviors to an object at runtime without altering core structure, by wrapping.
Inheritance doesn’t allow wrapping an object at runtime.
Composition allows a common method on every decorator to execute because decorators hold a reference to the object they are wrapping, forming a chain.
interface Product {
packing(): void
}
class ProductA implements Product {
packing(): void {
console.log("Packing");
}
}
// Base Decorator
class DecorableProduct implements Product {
protected product: Product;
constructor(product: Product) {
this.product = product;
}
packing(): void {
this.product.packing();
}
}
// Concrete decorators
class SafetyPackingDecorator extends DecorableProduct {
packing(): void {
console.log("Adding safety packing...");
this.product.packing();
}
}
class DecorativePackingDecorator extends DecorableProduct {
packing(): void {
console.log("Adding decorative packing...");
this.product.packing();
}
}
// Client
let product = new DecorativePackingDecorator(
new SafetyPackingDecorator(new ProductA())
)
product.packing()
It allows Anonymous Embedding if: