代理模式,相似於明星的經紀人,想要拜訪明星,須要先經過經紀人的溝通。而在JS當中,若是想訪問一個類,須要經過另外一個類來間接訪問 。不一樣於裝飾器,那種動態加載一個對象,能夠說在代理模式當中,代理是早已既定的。ajax
再拿最常遇到的收快遞這一個社會行爲舉例吧。
很早以前,咱們收發快遞都是直接和快遞員交互的,例如:
而如今,加入了代理以後,能夠經過第三方替咱們接收快遞,即:
這是生活當中一個很是常見的例子,能夠說代理的存在,大大的便利了「我」這個對象。下面就讓咱們在程序中看看代理是如何方便「我」的。緩存
程序作這樣一件事,即根據不一樣的快遞類型,來進行不一樣的操做(執行不一樣的函數),那麼在沒有引進代理以前,寫法多是這個樣子。
無代理:異步
class getDelivery { constructor() { } gets(a) { let fn1 = () => { setTimeout(() => { //some fns of fn1 console.log(`獲取快遞有:${a}`) }, 1000) } let fn2 = () => { setTimeout(() => { //some fns of fn2 console.log(`獲取快遞有:${a}`) }, 2000) } let fn3 = () => { setTimeout(() => { //some fns of fn3 console.log(`獲取快遞有:${a}`) }, 3000) } let deliver = {'中通': fn1, 'EMS': fn2, '順豐': fn3}[name]; return deliver(); } } getDelivery.prototype.proxyGets('中通')
定義一個類,上面的gets函數去判斷不一樣的快遞類型,而後去執行相對應的操做。函數
如今,當咱們引入代理模式以後,代碼多是這樣的:
代理:spa
class getDelivery { constructor() { } gets(a) { console.log(`獲取快遞有:${a}`) } } class proxy extends getDelivery { constructor() { super(); } proxyGets(name) { let fn1 = () => { setTimeout(() => { //some fns of fn1 super.gets('中通快遞') }, 1000) } let fn2 = () => { setTimeout(() => { //some fns of fn2 super.gets('EMS') }, 2000) } let fn3 = () => { setTimeout(() => { //some fns of fn3 super.gets('順豐') }, 3000) } let deliver = {'中通': fn1, 'EMS': fn2, '順豐': fn3}[name]; return deliver(); } } proxy.prototype.proxyGets('中通')
(ps:本代碼僅用於代理模式的示例,每次調用函數從新聲明fn1等方法是不對的)
ok,這兩種方法都會獲得這樣的結果:
然後者在代碼上還多了一些,但爲何這裏仍是推薦使用後面這種模式來寫代碼呢?prototype
首先介紹一個面向對象設計原則,單一職責原則。設計
又稱單一功能原則,面向對象五個基本原則(SOLID)之一。它規定一個類應該只有一個發生變化的緣由。所謂職責是指類變化的緣由。若是一個類有多於一個的動機被改變,那麼這個類就具備多於一個的職責。而單一職責原則就是指一個類或者模塊應該有且只有一個改變的緣由。代理
而在本例中,咱們並不關心是什麼快遞,關心的只是接到快遞觸發的結果,或者說接到快遞後,執行的任務纔是getDelivery 這個類的核心,至於中間的過程,應該交給專門處理他的類來判別。code
第二個原則:開放封閉原則對象
開放封閉原則(OCP,Open Closed Principle)是全部面向對象原則的核心。軟件設計自己所追求的目標就是封裝變化、下降耦合,而開放封閉原則正是對這一目標的最直接體現。其餘的設計原則,不少時候是爲實現這一目標服務的,例如以Liskov替換原則實現最佳的、正確的繼承層次,就能保證不會違反開放封閉原則。
還以接收快遞爲例,好比有一天,接收快遞的形勢變了,或者說,根本不須要判斷是什麼快遞,能夠隨時接收,那麼proxy 這個類其實就沒有用了,此時咱們能夠直接調用getDelivery這個類。可是,若是以第一種寫法的話,那就是無路可退了,只能去原對象中去刪掉相對應的邏輯。當代碼複雜程度變高的話,高耦合的程序,會讓人很是噁心。
代理模式,在實踐當中還能夠應用於緩存ajax異步數據,惰性加載等等方面,本文不詳細講解,僅做拋磚引玉的入門參考。