JavaScript設計模式淺析
設計模式最早的起源其實是源於建築學,針對某一個問題而提出的一個解決方案
01 前言
設計模式我們其實聽過不少,但是當別人問具體是什麼或者有哪些設計模式的時候,我們有可能會不知道或者回答不全。其實我們在開發的過程中可能很少會用到設計模式,因爲很多東西別人都幫我們封裝好了,我們直接拿過來用即可。
前端的開發經過一遍封裝過後變得無比容易,我們在運用的過程中得心應手,只有在源碼閱讀的過程中才會看到。大概瀏覽了一下JavaScript設計模式這本書,所以總結一下常用的幾種模式,面試也有可能會問到。
02 設計模式
工廠模式
故名思意,我們從字面上的意思就可以看到,可以想象一座工廠源源不斷產出一樣的產品,流水線作業。沒錯,工廠模式就是這樣。
class Person {
constructor(name) {
this.name = name
}
getName() {
console.log(this.name)
}
}
class Factory {
static create(name) {
return new Person(name)
}
}
Factory.create('alanwu').getName() //alanwu
我們首先創建一個工廠,我們只要傳遞參數進去,裏面具體的過程我們不用去關心,最後返回一個對象。
單例模式
單例模式就是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。其實這有一點像我們vuex當中的實現,也是一個全局的狀態管理,並且提供一個接口訪問。
var Singleton = function (name) {
this.name = name;
}
Singleton.prototype.getName = function () {
console.log(this.name);
}
Singleton.getInstance = (function(){
var instance = null;
return function(name){
if(!instance){
instance = new Singleton(name);
}
return instance;
}
}
)()
var a = Singleton.getInstance('alan1');
var b = Singleton.getInstance('alan2');
console.log(a===b); //true
適配器模式
適配器模式就相當於一個轉換接口,大家想想我們手機充電器通常是二岔口的,但是電源只有三岔口的。這時候就需要一個適配器把三岔口的轉換成二岔口的。
它的作用其實就是解決兩個軟件實體間的接口不兼容問題,使用之後就可以一起工作了。
var googleMap = {
show: function () {
console.log('googleMap show!');
}
}
var baiduMap = {
show: function () {
console.log('baiduMap show!');
}
}
var renderMap = function (map) {
if (map.show instanceof Function) {
map.show()
}
}
renderMap(googleMap);
renderMap(baiduMap);
上面這段程序能夠運行是因爲百度地圖和谷歌地圖用的同一種show方法,但是我們在不知道對方使用的函數接口的時候,我們就不能這樣用了(可能百度是使用了display方法來顯示)。下面的baiduMapAdapter就是我們使用的適配器。
var googleMap = {
show: function () {
console.log('googleMap show!');
}
}
var baiduMap = {
display: function () {
console.log('baiduMap show!');
}
}
var renderMap = function (map) {
if (map.show instanceof Function) {
map.show()
}
}
var baiduMapAdapter = {
show:function(){
return baiduMap.display()
}
}
renderMap(googleMap);
renderMap(baiduMapAdapter);
代理模式
我們在事件代理的時候其實就是使用了代理模式,通過把監聽事件全部交由父節點進行監聽,這樣你添加節點或者刪除節點的時候就不用去改變監聽的代碼。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let ul = document.querySelector('#ul')
ul.addEventListener('click', (event) => {
console.log(event.target);
})
</script>
發佈-訂閱模式
這種模式在生活中隨處可見,比如你訂閱了一個網課,開始前10分鐘就會提醒你去聽課。這裏其實就是發佈-訂閱的模式,你訂閱了它的開課信息,但是你不會接收到另一門的開課信息,因爲你沒有訂閱。
document.addEventListener('click', () => {
console.log("You click me!");
},false)
document.addEventListener('wheel', () => {
console.log("Your wheel!");
},false)
第一個是監聽點擊事件,而另一個是監聽滾輪事件,會打印出來不一樣的內容。
策略模式
根據情況進行不一樣的方案,比如你想去旅遊,明確自己有多少錢然後選擇旅遊方式。
- 沒錢,走路
- 有錢,飛機
- 還行,火車
這裏就涉及到策略的模式了。
var strategies = {
"rich": function () {
console.log("You can go with plane!");
},
"poor": function () {
console.log("OH, You can go with your feet!");
},
"middle": function () {
console.log("You can go with train!");
}
}
var howShouldGo = function (money) {
return strategies[money]();
}
console.log(howShouldGo("rich"));
迭代器模式
迭代器模式是指提供一種按順序訪問的方法。比如說我們經常使用的forEach方法,就是通過順序訪問的模式。我們可以自己去寫一下forEach的方法。
var myForEach = function (arr, callback) {
for (var i = 0, l = arr.length; i < l; i++) {
callback.call(arr[i], i, arr[i]) //把元素以及下標傳遞出去
}
}f
myForEach([1, 2, 3], function (item, n) {
console.log([item, n]);
})
//[ 0, 1 ]
//[ 1, 2 ]
//[ 2, 3 ]
03 小結
其實設計模式我們用的地方也是有的,只是我們沒有注意而已。上面我們說了都是常見的設計模式,還有很多我們沒有印象的比如命令模式,享元模式,組合模式,中介模式等等。
如果有興趣的同學可以去看一下JavaScript設計模式這本書,裏面說的都是比較詳細的。我大概讀了一遍,上面的一些例子也是書本當中的。