39 設(shè)計模式
設(shè)計模式可以分為三大類:
- 結(jié)構(gòu)型模式:通過識別系統(tǒng)中組件間的簡單關(guān)系來簡化系統(tǒng)色設(shè)計
- 創(chuàng)建型模式:處理對象的創(chuàng)建颤难,根據(jù)實際情況使用合適的方式創(chuàng)建對象
- 行為型模式:用于識別對象之間常見的交互模式并加以實現(xiàn)缝裤,如此增加了這些交互的靈活性。
39.1 工廠模式
說明:你可以想象一個場景恰矩,假設(shè)有一份很復(fù)雜的代碼需要用戶去調(diào)用,但是用戶并不關(guān)心這些復(fù)雜的代碼溶推,只需要你提供一個接口去調(diào)用,用戶只負責(zé)傳遞需要的參數(shù)癣疟,至于這個參數(shù)怎么使用,內(nèi)部邏輯不用關(guān)心潮酒,只需要你最后返回一個實例,這個構(gòu)造過程就是工廠邪蛔。
工廠起到的作用就是隱藏了創(chuàng)建實例的復(fù)雜度急黎,只需要一個接口,簡單清晰侧到。
現(xiàn)實生活中的工廠按照既定的程序制造產(chǎn)品勃教,隨著生產(chǎn)原料和流程不同生產(chǎn)出來的產(chǎn)品也會有區(qū)別。應(yīng)用到軟件工廠的領(lǐng)域匠抗,工廠可以看成是一個制造其他對象的對象故源,制造出來的對象也會隨著傳入共產(chǎn)對象的參數(shù)的不同而有所區(qū)別
那么,什么時候適合使用共產(chǎn)模式而不是直接new一個對象呢汞贸?當(dāng)構(gòu)造函數(shù)過多不便管理绳军,且需要創(chuàng)建的對象之間存在某些關(guān)聯(lián)(有同一個父類,實現(xiàn)同一個接口)時矢腻,不妨使用工廠模式门驾,工廠模式提供一種集中化,統(tǒng)一化的方式多柑,避免了分散創(chuàng)建對象導(dǎo)致的代碼重復(fù)奶是、靈活性差的問題。
舉例如下:(構(gòu)造一個簡單的汽車工廠來生產(chǎn)汽車)
//汽車構(gòu)造函數(shù)
function Car1(color) {
this.color = color
this.brand = 'Car1'
}
//汽車構(gòu)造函數(shù)
function Car2(color) {
this.color = color;
this.brand = 'Car2'
}
//汽車構(gòu)造函數(shù)
function Car3(color) {
this.color = color;
this.brand = 'Car3'
}
//汽車的品牌
const BRANDS = {
car1: 1,
car2: 2,
car3: 3
}
//汽車工廠
function createCar() {
this.create = function (brand, color) {
switch (brand) {
case BRANDS.car1:
return new Car1(color);
case BRANDS.car2:
return new Car2(color);
case BRANDS.car3:
return new Car3(color);
default:
break;
}
}
}
//測試
const carFactory = new createCar();
const cars = [];
cars.push(carFactory.create(BRANDS.car1, 'red'))
cars.push(carFactory.create(BRANDS.car2, 'greed'))
cars.push(carFactory.create(BRANDS.car3, 'pink'))
function say() {
console.log(`Hi , I am ${this.color} and ${this.brand} car`)
}
for (const car of cars) {
say.call(car)
}
結(jié)果如下
使用工廠模式后竣灌,不再需要重復(fù)引入一個個構(gòu)造函數(shù)聂沙,只需要引入工廠對象便可以創(chuàng)建各類對象
39.2 單例模式
單例模式的核心就是保證全局只有一個對象可以訪問,Class的實例個數(shù)最多為1初嘹,一般全局緩存及汉、全局狀態(tài)管理等待這些只需要一個對象,就可以使用單例模式削樊。 即我們只需要用一個變量確保實例只創(chuàng)建一次就可以豁生,以下為其實例:
class Singleton {
constructor() {
}
}
Singleton.getInstance = (function () {
let instance;
return function () {
//這里使用的閉包,使用閉包保存局部作用域中的單例對象并返回
if (!instance) {
instance = new Singleton();
}
return instance;
}
})()
let s1 = new Singleton.getInstance();
let s2 = new Singleton.getInstance();
console.log(s1 === s2) //true
設(shè)計思路:即當(dāng)instance為空時漫贞,則new創(chuàng)建新對象甸箱,若不為空時返回原來的instance對象,因此使得每次都是同一個對象
39.3 代理模式
代理是為了控制對對象的訪問迅脐,不讓外部直接訪問到對象芍殖,也有很多代理的場景。比如事件代理就用到了代理模式谴蔑。
<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', function (event) {
console.log(event.target)
})
</script>
因為存在太多的li豌骏,不可能內(nèi)個都去綁定事件龟梦,這時可以通過給父節(jié)點綁定一個事件,讓父節(jié)點作為代理去拿到真實點擊的節(jié)點窃躲。
39.4 發(fā)布-訂閱者模式
發(fā)布-訂閱者模式也叫作觀察者模式计贰。通過一對一或者一對多的依賴關(guān)系,當(dāng)對象發(fā)生改變時蒂窒,訂閱方也會收到通知躁倒。
在現(xiàn)實生活中如商品缺貨時點擊有貨通知的按鈕
在實際代碼中如我們點擊一個按鈕觸發(fā)了點擊事件就是使用了觀察者模式
let ul = document.querySelector('#ul');
ul.addEventListener('click', function (event) {
console.log(event.target)
})
39.5 外觀模式
外觀模式提供一個接口,隱藏了內(nèi)部的邏輯洒琢,更加方便外部調(diào)用
比如兼容多個瀏覽器添加時間就是使用外觀模式
function addEvent(ele, ebType, fn, useCapture) {
if (ele.addEventListener) {
ele.addEventListener(evType, fn, useCapture);
return true
} else if (ele.attachEvent) {
var r = ele.attachEvent("on" + evType, fn)
return r;
} else {
//均支持這種事件綁定方式
ele["on" + evType] = fn
}
}
對于不同瀏覽器秧秉,添加的事件的方式可能會存在兼容問題。如果誒次都需要去這樣寫一遍的話肯定是不能接受的衰抑,所以我們將這些判斷邏輯統(tǒng)一封裝在一個接口中象迎,外部需要添加時間時只需要調(diào)用addEvent即可。
————————————————
原文鏈接:https://blog.csdn.net/weixin_46872121/article/details/111936904