今天要介绍的装饰器模式,跟之前提到过的转接器模式有点类似(但其实结果完全不一样)。
转接器模式的功能在於将让现有的物件可以透过转接器,能够实现自己没有的介面或功能。而装饰器的功能在於,维持现有物件既有的介面和功能,但是在执行细节上「加料」。
让我们来看看下面的例子。假设这里有个 Printer
的抽象类别,接着 MagazinePrinter
和 BookPrinter
继承 Printer
并实作 print
方法
abstract class Printer {
abstract print(): void
}
class MagazinePrinter extends Printer {
genre: string;
constructor(genre: string) {
super()
this.genre = genre
}
print(): string {
return `This is a ${this.genre} magazine!`
}
}
class BookPrinter extends Printer {
genre: string;
constructor(genre: string) {
super()
this.genre = genre
}
print(): string {
return `This is a ${this.genre} book!`
}
}
最後,我们就可以建立实例,执行 print
方法得到结果
const economyMagazine = new MagazinePrinter('economy')
const scienceBook = new BookPrinter('science')
economyMagazine.print() // This is a economy magazine!
scienceBook.print() // This is a science book!
这时候书店老板来了,他说这个月刚好周年庆,因此希望能够在书印出来之後,也印上 "Best sell!" 的字来刺激买气。
如果只是因为要为了这一个月的促销活动,然後建立新的类别,似乎有点大费周章。这时候意旁的工程师说,不如我们就用装饰器来装饰原有的物件吧!
这里我们建立一个 PromotionDecorator
,同样继承 Printer
,因此需要实作 print
方法。
不过比较特别的是,这里我们并不直接实作 print
,而是间接依赖其他 printer 执行 print
方法,然後我们在装饰器当中加点料,像是下面这样
class PromotionDecorator extends Printer {
printer: Printer;
constructor(printer: Printer){
super()
this.printer = printer
}
print(): string {
return `${this.printer.print()} (Best sell!)`
}
}
之後我们只要传入需要被装饰的实例到装饰器当中,建立新的、被装饰过的实例,执行 print
方法之後,就可以得到我们想要的结果罗!
const magazine = new PromotionDecorator(economyMagazine)
const book = new PromotionDecorator(scienceBook)
magazine.print() // This is a economy magazine! (Best sell!)
book.print() // This is a science book! (Best sell!)
使用装饰器的好处是,可以快速延伸原有物件的功能,而且不用建立任何新的物件。而多个装饰器可以层层嵌套,因此可以快速建立多样化的功能。
但反过来说,在层层嵌套的情况下,一旦中间其中一个装饰器需要变更行为或移除,就会造成一些麻烦。
<<: [Day 25]从零开始学习 JS 的连续-30 Days---addEventListener 事件监听
Hello, 各位 iT邦帮忙 的粉丝们大家好~~~ 本篇是 Re: 从零开始用 Xamarin 技...
前言 上一篇我们讨论DDD的战术设计,它建议引用各种设计模式,提高生产力,因此接下来,就来介绍各种设...
看完这篇文章你会得到的成果图 前言 这篇我们要来学一个新的东西 QTimer! QTimer 是独立...
刚读大一的时候,最让我感到头痛的就是程序设计课了!因为我一直以来都不怎麽喜欢电脑相关的东西,更别说是...
此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 当测试脚本有重复的地方,除了可以写...