Skip to main content

Decorator

  • 重写/重载/扩展对象原有的行为 (Methods), 但不改变对象原有属性.
  • 可以添加新属性, 并围绕新属性扩展对象的原行为 e.g. 原对象只会说中文, 装饰后同时说中文与英文.
  • 避免了通过继承来为类型添加新职责, 通过继承的方式容易造成子类的膨胀.
  • 保持接口的一致性, 动态改变对象的外观/职责.
  • ConcreteDecorator 类: private ClassName component 拥有一个对象引用.
  • 在 JS 中, 可以利用 Closure (闭包) + Higher Order Function (高阶函数) 快速实现装饰器模式.
  • 符合开放封闭原则和单一职责模式.
Decorator Use Case
  • Graphics and UI Frameworks: e.g. extended React HOC components.
  • ES2016 and TypeScript @decorator.
  • Guard: form validator.
  • Interceptor:
    • HTTP request and response decorator.
    • Web statistic tool.
  • Transformer.
  • AOP: Aspect Oriented Programming.
function __decorate(decorators, target) {
const decorateTarget = target

for (const decorator of decorators)
decorateTarget = decorator(decorateTarget) || decorateTarget

return decorateTarget
}
class MacBook {
constructor() {
this.cost = 997
this.screenSize = 11.6
}

getCost() {
return this.cost
}

getScreenSize() {
return this.screenSize
}
}

// Decorator 1
class Memory extends MacBook {
constructor(macBook) {
super()
this.macBook = macBook
}

getCost() {
return this.macBook.getCost() + 75
}
}

// Decorator 2
class Engraving extends MacBook {
constructor(macBook) {
super()
this.macBook = macBook
}

getCost() {
return this.macBook.getCost() + 200
}
}

// Decorator 3
class Insurance extends MacBook {
constructor(macBook) {
super()
this.macBook = macBook
}

getCost() {
return this.macBook.getCost() + 250
}
}

let mb = new MacBook()
mb = new Memory(mb)
mb = new Engraving(mb)
mb = new Insurance(mb)

console.log(mb.getCost())
// Outputs: 1522
console.log(mb.getScreenSize())
// Outputs: 11.6