Decorator đính kèm thêm behavior vào object tại runtime bằng cách bọc chúng trong decorator objects — thay thế cho inheritance khi cần linh hoạt.
Ví dụ TypeScript:
typescript
interface Coffee { cost(): number }
class SimpleCoffee implements Coffee {
cost() { return 10 }
}
class MilkDecorator implements Coffee {
constructor(private coffee: Coffee) {}
cost() { return this.coffee.cost() + 2 }
}
class SugarDecorator implements Coffee {
constructor(private coffee: Coffee) {}
cost() { return this.coffee.cost() + 1 }
}
// Stack decorators:
const myCoffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()))
myCoffee.cost() // 13Khác Inheritance: Decorator thêm behavior tại runtime và có thể stack nhiều lớp; inheritance static tại compile time và có thể gây explosion.
- TypeScript
@decoratorsyntax là Decorator pattern nhưng dành cho class/method metadata, không hẳn là GoF Decorator. - Dùng khi: cần thêm behavior mà không muốn sửa class gốc; khi cần combine nhiều behavior tùy chọn.
- Không dùng khi: decorator stack quá sâu gây khó debug.
Decorator attaches additional behavior to an object at runtime by wrapping it in decorator objects — an alternative to inheritance when flexibility is needed.
TypeScript example:
typescript
interface Coffee { cost(): number }
class SimpleCoffee implements Coffee {
cost() { return 10 }
}
class MilkDecorator implements Coffee {
constructor(private coffee: Coffee) {}
cost() { return this.coffee.cost() + 2 }
}
class SugarDecorator implements Coffee {
constructor(private coffee: Coffee) {}
cost() { return this.coffee.cost() + 1 }
}
// Stack decorators:
const myCoffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()))
myCoffee.cost() // 13Difference from Inheritance: Decorator adds behavior at runtime and allows stacking multiple layers; inheritance is static at compile time and can cause class explosion.
- TypeScript's
@decoratorsyntax is related to the Decorator concept but serves class/method metadata, which is not exactly the GoF Decorator. - Use it when you need to add behavior without modifying the original class, or when you need to combine several optional behaviors.
- Avoid it when the decorator stack becomes too deep, making debugging difficult.