今天要談到代理模式,其實跟昨天的裝飾器模式很類似。代理模式的目的在於,因應某些條件替換物件原本的行為。
同樣用昨天的例子,這裡有 BookPrinter
可以把書印出來
abstract class Printer {
abstract print(): void
}
class BookPrinter extends Printer {
genre: string;
constructor(genre: string) {
super()
this.genre = genre
}
print(): string {
return `This is a ${this.genre} book!`
}
}
但我們希望這個 BookPrinter
只有在 "ready" 的時候才印書,如果尚未 "ready" 的話,就讓使用者知道 printer 還沒有準備好。這時候我們可以怎麼做呢?
首先,我們建立一個 BookPrinterProxy
類別。跟昨天的裝飾器很像,我們可以傳入物件到這個 proxy 當中,再由這個 proxy 幫我們「加料」做點事情。
這裡我們要做的事情就是,判斷 printer 是否 ready。這裡假設有一個 isReady 的變數,如果為 true,那麼就執行原有物件的功能;若為 false,那麼就讓 proxy 代為處理,印出 "Printer is not ready" 的訊息
class BookPrinterProxy extends Printer {
printer: Printer;
constructor(printer: Printer){
super()
this.printer = printer
}
print(): string {
if (isReady) {
return `${this.printer.print()}`
} else {
return 'Printer is not ready!'
}
}
}
實作結果如下:
const scienceBook = new BookPrinter('science')
const bookProxy = new BookPrinterProxy(scienceBook)
let isReady = false
bookProxy.print() // Printer is not ready!
isReady = true
bookProxy.print() // This is a science book!
代理模式其實在平常的開發當中很常見,譬如協助我們管理權限、快取等等,讓我們可以不用更動原本的物件的情況下,面對其他各種狀況。
代理模式可以說是特別版的裝飾器模式,差別在於裝飾器模式著重在層層套嵌的擴展性,而代理模式則著重於面對不同條件下的應對(代理)方式。