1. 程式人生 > 其它 >前端常用的設計模式

前端常用的設計模式

轉載自:https://zhuanlan.zhihu.com/p/115874575

一、常用設計模式

1、單例模式:確保只有一個例項,並提供全域性訪問。

2、策略模式:定義一些列的演算法,把它們一個個封裝起來,並且使它們可以相互替換。

3、代理模式:為一個物件提供一個代用品或佔位符,以便控制對它的訪問。js裡虛擬代理(網路請求方面)、快取代理(資料方面)最常用

4、迭代器模式:提供一種方法,順序訪問一個聚合物件中的各個元素,而又不需要暴露該物件的內部表示。不需要關心物件的內部構造,也可以按順序訪問其中的每個元素。很多語言都有自己內建的迭代器,比如js的Array.prototype.forEach

5、釋出-訂閱模式:又叫

觀察者模式,它定義物件間的一種一對多的依賴關係,當一個物件的狀態生改變時,所有依賴於它的物件都將得到通知。在js中,一般用事件模型代替它。

var a={} a.b={} a.c=function(key,fn){   if(!this.b[key]){     this.b[key]=[]      }   this.b[key].push(fn) } a.d=function(){   var key =Array.prototype.shift.call(arguments),       fns=this.b[key]     console.log(arguments)   if(!fns||fns.length===0){     return false;      }   for(var i=0,fn;fn=fns[i++];){     fn.apply(this,arguments)   } } a.c('88',function(pri){     console.log(pri) }) a.c('110',function(pri){     console.log(pri) }) a.d('88',200) a.d('110',300)

6、命令模式:執行某些特定事情的指令。記錄資訊的清單,就是命令模式中的命令物件。

PS:有時候,需要像某些物件傳送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是什麼。這時候就需要命令模式,使得請求傳送者和請求接收者能夠消除耦合關係。

7、組合模式:使用樹形方式建立物件的結構,把相同的操作應用在組合物件和單個物件上。

8、模板方法模式:只需要整合就可以實現,由兩部分組成,第一部分是抽象類,第二部分是具體的實現子類。通常在抽象父類中封裝了子類的演算法框架,包括實現一些公共方法以及封裝子類中所有方法的執行順序。子類通過繼承這個抽象類,也繼承了整個演算法結構,並且可以選擇重寫父類的方法。

//抽象類 var a=function(){}; a.prototype.b=function(){     console.log('把水煮沸') } a.prototype.c=function(){} a.prototype.d=function(){} a.prototype.e=function(){} a.prototype.init=function(){     this.b();     this.c();     this.d();     this.e(); } //子類 var g=function(){} g.prototype.c=function(){     console.log('用沸水衝咖啡') } g.prototype.d=function(){     console.log('把咖啡倒進杯子') } g.prototype.e=function(){     console.log('加糖和牛奶') } var h=new g() h.init()
這裡的a.prototype.init就是模板方法

9、好萊塢原則:即高層元件呼叫底層元件,模板方法是好萊塢的一個典型使用場景;子類放棄了對自己的控制權,而是改為父類通知子類哪些方法應該在什麼時候被呼叫。作為子類,只負責提供一些設計上的細節。

Ps:釋出-訂閱模式、回撥函式都用到了此原則

10、享元模式:運用共享技術來有效支援大量細粒度的物件。

Ps:

  1. 內部狀態儲存與物件內部。
  2. 內部狀態可以被一些物件共享。
  3. 內部狀態獨立於具體的場景,通常不會改變。
  4. 外部狀態取決於具體的場景,並根據場景而變化,外部狀態不能被共享。

11、物件池:維護一個裝在空閒物件的池子,如果需要物件的時候,不是直接new,而是轉從物件池裡獲取。如果物件池裡沒有空閒物件,則建立一個新的物件,當獲取出的物件完成它的職責後,再進入池子等待被下次獲取;

12、職責鏈模式:使多個物件都有機會處理請求,並從而避免請求的傳送者和接收者之間的耦合關係,將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。

PS:有多個if-else條件的時候,要去考慮是否可以用職責鏈模式。

13、中介者模式:解除物件與物件之間得耦合關係。增加一個中介者物件後,所有得相關物件都通過中介者物件來通訊,而不是互相引用,所有當一個物件發生改變時,只需要通知中介者物件即可。此模式迎合迪米特法則的一種實現,迪米特也叫做最少知識原則,是指一個物件應該儘可能少地瞭解另外的物件。

PS:編寫思路:1、利用釋出-訂閱模式2、在中介者物件中開放一些接收訊息得介面

14、裝飾者模式:給物件動態地增加職責。這種方式並沒有真正地改動物件自身,而是將物件放入另一個物件之中,這些物件以一條鏈的方式進行引用,形成一個聚合物件。

PS:經常用到Function.pototype.after和Function.pototype.before兩個函式進行裝飾

Function.prototype.before=function(beforefn){      var _self=this;//儲存原函式引用 return function(){// 返回包含了原函式和新函式的“代理”函式          beforefn.apply(this,arguments);// 執行新函式,且保證this不被劫持,新函式接受的引數也會被原封不動地傳入原函式,新函式在原函式之前執行 return _self.apply(this,arguments);// 執行原函式並返回原函式的執行結果,並且保證this不被劫持      }  }   

注意:這裡的beforefn和原函式_self共用一組引數列表arguments,當我們在beforefn的函式體內改變arguments的時候,_self接收的引數列表自然也會變化,所以經常用於動態地改變原函式的引數

15、狀態模式:關鍵是區分事物內部的狀態,事物內部狀態的改變往往會帶來事物的行為改變。此模式關鍵是把事物的每種狀態都封裝成單獨的類。

PS:狀態模式和策略模式區別:

策略模式的各個策略類之間是平等又平行的,他們之間沒有任何聯絡,所以客戶必須熟知這些策略類的作用。以便隨時切換演算法;而狀態模式,狀態和狀態對應的行為早已被封裝好的,狀態之間的切換也早被規定完成,“改變行為”這件事發生在狀態模式內部。對客戶來說,並不需要了解這些細節,這正是狀態模式的作用所在。

16、介面卡模式:解決兩個軟體實體的介面不相容的問題。不考慮介面是怎樣實現的,也不考慮將來可能會如何讓變化,介面卡模式不需要改變已有的介面,就能夠使他們協同作用,介面卡模式通常只包裝一次。

var a={     show:function(){         console.log('a資料來源開始渲染')     } } var b={     disply:function(){         console.log('b資料來源開始渲染')     } } //介面卡c var c={     show:function(){         return b.disply();     } } var render=function(fn){     fn.show() } render(a) render(c)

17、外觀模式:在JS中不常用。主要是為子系統中的一組介面提供一個一致的介面,定義了一個高層的介面,這個介面使子系統更加容易使用。在C++或者JAVA中指的是一組類的集合,這些類相互協作可以組成系統中一個相對獨立的部分。但在JS中,這個子系統至少應該指的是一組函式的集合。

var A=function(){     a1()     a2() }